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-2017 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 (highest addressable byte) for the client's stack. */
     62 extern Addr VG_(am_startup) ( Addr sp_at_startup );
     63 
     64 /* Check whether ADDR is OK to be used as aspacem_minAddr. If not, *ERRMSG
     65    will be set to identify what's wrong. ERRMSG may be NULL. */
     66 extern Bool VG_(am_is_valid_for_aspacem_minAddr)( Addr addr,
     67                                                   const HChar **errmsg );
     68 
     69 //--------------------------------------------------------------
     70 // Querying current status
     71 
     72 
     73 /* Finds an anonymous segment containing 'a'. Returned pointer is read only. */
     74 extern NSegment const *VG_(am_find_anon_segment) ( Addr a );
     75 
     76 /* Find the next segment along from 'here', if it is a file/anon/resvn
     77    segment. */
     78 extern NSegment const* VG_(am_next_nsegment) ( const NSegment* here,
     79                                                Bool fwds );
     80 
     81 /* Is the area [start .. start+len-1] validly accessible by
     82    valgrind with at least the permissions 'prot' ?  To find out
     83    simply if said area merely belongs to valgrind, pass
     84    VKI_PROT_NONE as 'prot'.  Will return False if any part of the
     85    area does not belong to valgrind or does not have at least
     86    the stated permissions. */
     87 extern Bool VG_(am_is_valid_for_valgrind)
     88    ( Addr start, SizeT len, UInt prot );
     89 
     90 /* Variant of VG_(am_is_valid_for_client) which allows free areas to
     91    be consider part of the client's addressable space.  It also
     92    considers reservations to be allowable, since from the client's
     93    point of view they don't exist. */
     94 extern Bool VG_(am_is_valid_for_client_or_free_or_resvn)
     95    ( Addr start, SizeT len, UInt prot );
     96 
     97 /* Checks if a piece of memory consists of either free or reservation
     98    segments. */
     99 extern Bool VG_(am_is_free_or_resvn)( Addr start, SizeT len );
    100 
    101 /* Check whether ADDR looks like an address or address-to-be located in an
    102    extensible client stack segment. */
    103 extern Bool VG_(am_addr_is_in_extensible_client_stack)( Addr addr );
    104 
    105 /* Trivial fn: return the total amount of space in anonymous mappings,
    106    both for V and the client.  Is used for printing stats in
    107    out-of-memory messages. */
    108 extern ULong VG_(am_get_anonsize_total)( void );
    109 
    110 /* Show the segment array on the debug log, at given loglevel. */
    111 extern void VG_(am_show_nsegments) ( Int logLevel, const HChar* who );
    112 
    113 /* VG_(am_get_segment_starts) is also part of this section, but its
    114    prototype is tool-visible, hence not in this header file. */
    115 
    116 /* Sanity check: check that Valgrind and the kernel agree on the
    117    address space layout.  Prints offending segments and call point if
    118    a discrepancy is detected, but does not abort the system.  Returned
    119    Bool is False if a discrepancy was found. */
    120 
    121 extern Bool VG_(am_do_sync_check) ( const HChar* fn,
    122                                     const HChar* file, Int line );
    123 
    124 //--------------------------------------------------------------
    125 // Functions pertaining to the central query-notify mechanism
    126 // used to handle mmap/munmap/mprotect resulting from client
    127 // syscalls.
    128 
    129 /* Describes a request for VG_(am_get_advisory). */
    130 typedef
    131    struct {
    132       /* Note: if rkind == MAlign then start specifies alignment. This is
    133          Solaris specific. */
    134       enum { MFixed, MHint, MAny, MAlign } rkind;
    135       Addr start;
    136       Addr len;
    137    }
    138    MapRequest;
    139 
    140 /* Query aspacem to ask where a mapping should go.  On success, the
    141    advised placement is returned, and *ok is set to True.  On failure,
    142    zero is returned and *ok is set to False.  Note that *ok must be
    143    consulted by the caller to establish success or failure; that
    144    cannot be established reliably from the returned value.  If *ok is
    145    set to False, it means aspacem has vetoed the mapping, and so the
    146    caller should not proceed with it. */
    147 extern Addr VG_(am_get_advisory)
    148    ( const MapRequest* req, Bool forClient, /*OUT*/Bool* ok );
    149 
    150 /* Convenience wrapper for VG_(am_get_advisory) for client floating or
    151    fixed requests.  If start is zero, a floating request is issued; if
    152    nonzero, a fixed request at that address is issued.  Same comments
    153    about return values apply. */
    154 extern Addr VG_(am_get_advisory_client_simple)
    155    ( Addr start, SizeT len, /*OUT*/Bool* ok );
    156 
    157 /* Returns True if [start, start + len - 1] is covered by a single
    158    free segment, otherwise returns False.
    159    This allows to check the following case:
    160    VG_(am_get_advisory_client_simple) (first arg == 0, meaning
    161    this-or-nothing) is too lenient, and may allow us to trash
    162    the next segment along.  So make very sure that the proposed
    163    new area really is free.  This is perhaps overly
    164    conservative, but it fixes #129866. */
    165 extern Bool VG_(am_covered_by_single_free_segment)
    166    ( Addr start, SizeT len);
    167 
    168 /* Notifies aspacem that the client completed an mmap successfully.
    169    The segment array is updated accordingly.  If the returned Bool is
    170    True, the caller should immediately discard translations from the
    171    specified address range. */
    172 extern Bool VG_(am_notify_client_mmap)
    173    ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset );
    174 
    175 /* Notifies aspacem that the client completed a shmat successfully.
    176    The segment array is updated accordingly.  If the returned Bool is
    177    True, the caller should immediately discard translations from the
    178    specified address range. */
    179 extern Bool VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot );
    180 
    181 /* Notifies aspacem that an mprotect was completed successfully.  The
    182    segment array is updated accordingly.  Note, as with
    183    VG_(am_notify_munmap), it is not the job of this function to reject
    184    stupid mprotects, for example the client doing mprotect of
    185    non-client areas.  Such requests should be intercepted earlier, by
    186    the syscall wrapper for mprotect.  This function merely records
    187    whatever it is told.  If the returned Bool is True, the caller
    188    should immediately discard translations from the specified address
    189    range. */
    190 extern Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot );
    191 
    192 /* Notifies aspacem that an munmap completed successfully.  The
    193    segment array is updated accordingly.  As with
    194    VG_(am_notify_mprotect), we merely record the given info, and don't
    195    check it for sensibleness.  If the returned Bool is True, the
    196    caller should immediately discard translations from the specified
    197    address range. */
    198 extern Bool VG_(am_notify_munmap)( Addr start, SizeT len );
    199 
    200 /* Hand a raw mmap to the kernel, without aspacem updating the segment
    201    array.  THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view
    202    of the address space to diverge from that of the kernel.  DO NOT
    203    USE IT UNLESS YOU UNDERSTAND the request-notify model used by
    204    aspacem.  In short, DO NOT USE THIS FUNCTION. */
    205 extern SysRes VG_(am_do_mmap_NO_NOTIFY)
    206    ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset);
    207 
    208 
    209 //--------------------------------------------------------------
    210 // Dealing with mappings which do not arise directly from the
    211 // simulation of the client.  These are typically used for
    212 // loading the client and building its stack/data segment, before
    213 // execution begins.  Also for V's own administrative use.
    214 
    215 /* --- --- --- map, unmap, protect  --- --- --- */
    216 
    217 /* Map a file at a fixed address for the client, and update the
    218    segment array accordingly. */
    219 extern SysRes VG_(am_mmap_file_fixed_client)
    220    ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset );
    221 extern SysRes VG_(am_mmap_file_fixed_client_flags)
    222    ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset );
    223 extern SysRes VG_(am_mmap_named_file_fixed_client)
    224    ( Addr start, SizeT length, UInt prot, Int fd,
    225      Off64T offset, const HChar *name );
    226 extern SysRes VG_(am_mmap_named_file_fixed_client_flags)
    227    ( Addr start, SizeT length, UInt prot, UInt flags, Int fd,
    228      Off64T offset, const HChar *name );
    229 
    230 /* Map anonymously at a fixed address for the client, and update
    231    the segment array accordingly. */
    232 extern SysRes VG_(am_mmap_anon_fixed_client)
    233    ( Addr start, SizeT length, UInt prot );
    234 
    235 
    236 /* Map anonymously at an unconstrained address for the client, and
    237    update the segment array accordingly.  */
    238 extern SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot );
    239 
    240 /* Map anonymously at an unconstrained address for V, and update the
    241    segment array accordingly.  This is fundamentally how V allocates
    242    itself more address space when needed. */
    243 extern SysRes VG_(am_mmap_anon_float_valgrind)( SizeT cszB );
    244 
    245 /* Map privately a file at an unconstrained address for V, and update the
    246    segment array accordingly.  This is used by V for transiently
    247    mapping in object files to read their debug info.  */
    248 extern SysRes VG_(am_mmap_file_float_valgrind)
    249    ( SizeT length, UInt prot, Int fd, Off64T offset );
    250 
    251 /* Map shared a file at an unconstrained address for V, and update the
    252    segment array accordingly.  This is used by V for communicating
    253    with vgdb.  */
    254 extern SysRes VG_(am_shared_mmap_file_float_valgrind)
    255    ( SizeT length, UInt prot, Int fd, Off64T offset );
    256 
    257 /* Similar to VG_(am_mmap_anon_float_client) but also
    258    marks the segment as containing the client heap. */
    259 extern SysRes VG_(am_mmap_client_heap) ( SizeT length, Int prot );
    260 
    261 /* Unmap the given address range and update the segment array
    262    accordingly.  This fails if the range isn't valid for the client.
    263    If *need_discard is True after a successful return, the caller
    264    should immediately discard translations from the specified address
    265    range. */
    266 extern SysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard,
    267                                      Addr start, SizeT length );
    268 
    269 /* Let (start,len) denote an area within a single Valgrind-owned
    270   segment (anon or file).  Change the ownership of [start, start+len)
    271   to the client instead.  Fails if (start,len) does not denote a
    272   suitable segment. */
    273 extern Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len );
    274 
    275 /* Set the 'hasT' bit on the segment containing ADDR indicating that
    276    translations have or may have been taken from this segment. ADDR is
    277    expected to belong to a client segment. */
    278 extern void VG_(am_set_segment_hasT)( Addr addr );
    279 
    280 /* --- --- --- reservations --- --- --- */
    281 
    282 /* Create a reservation from START .. START+LENGTH-1, with the given
    283    ShrinkMode.  When checking whether the reservation can be created,
    284    also ensure that at least abs(EXTRA) extra free bytes will remain
    285    above (> 0) or below (< 0) the reservation.
    286 
    287    The reservation will only be created if it, plus the extra-zone,
    288    falls entirely within a single free segment.  The returned Bool
    289    indicates whether the creation succeeded. */
    290 extern Bool VG_(am_create_reservation)
    291    ( Addr start, SizeT length, ShrinkMode smode, SSizeT extra );
    292 
    293 /* ADDR is the start address of an anonymous client mapping.  This fn extends
    294    the mapping by DELTA bytes, taking the space from a reservation section
    295    which must be adjacent.  If DELTA is positive, the segment is
    296    extended forwards in the address space, and the reservation must be
    297    the next one along.  If DELTA is negative, the segment is extended
    298    backwards in the address space and the reservation must be the
    299    previous one.  DELTA must be page aligned.  abs(DELTA) must not
    300    exceed the size of the reservation segment minus one page, that is,
    301    the reservation segment after the operation must be at least one
    302    page long. The function returns a pointer to the resized segment. */
    303 extern const NSegment *VG_(am_extend_into_adjacent_reservation_client)
    304    ( Addr addr, SSizeT delta, /*OUT*/Bool *overflow );
    305 
    306 /* --- --- --- resizing/move a mapping --- --- --- */
    307 
    308 /* This function grows a client mapping in place into an adjacent free segment.
    309    ADDR is the client mapping's start address and DELTA, which must be page
    310    aligned, is the growth amount. The function returns a pointer to the
    311    resized segment. The function is used in support of mremap. */
    312 extern const NSegment *VG_(am_extend_map_client)( Addr addr, SizeT delta );
    313 
    314 /* Remap the old address range to the new address range.  Fails if any
    315    parameter is not page aligned, if the either size is zero, if any
    316    wraparound is implied, if the old address range does not fall
    317    entirely within a single segment, if the new address range overlaps
    318    with the old one, or if the old address range is not a valid client
    319    mapping.  If *need_discard is True after a successful return, the
    320    caller should immediately discard translations from both specified
    321    address ranges.  */
    322 extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
    323                                                Addr old_addr, SizeT old_len,
    324                                                Addr new_addr, SizeT new_len );
    325 
    326 //--------------------------------------------------------------
    327 // Valgrind (non-client) thread stacks.  V itself runs on such
    328 // stacks.  The address space manager provides and suitably
    329 // protects such stacks.
    330 
    331 // VG_DEFAULT_STACK_ACTIVE_SZB is the default size of a Valgrind stack.
    332 // The effectively used size is controlled by the command line options
    333 // --valgrind-stack-size=xxxx (which must be page aligned).
    334 // Note that m_main.c needs an interim stack (just to startup), before
    335 // any command line option can be processed. This interim stack
    336 // (declared in m_main.c) will use the size VG_DEFAULT_STACK_ACTIVE_SZB.
    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 #else
    343 # define VG_STACK_GUARD_SZB  8192   // 2 pages
    344 #endif
    345 # define VG_DEFAULT_STACK_ACTIVE_SZB 1048576 // (4096 * 256) = 1Mb
    346 
    347 typedef struct _VgStack VgStack;
    348 
    349 
    350 /* Allocate and initialise a VgStack (anonymous valgrind space).
    351    Protect the stack active area and the guard areas appropriately.
    352    Returns NULL on failure, else the address of the bottom of the
    353    stack.  On success, also sets *initial_sp to what the stack pointer
    354    should be set to. */
    355 
    356 extern VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp );
    357 
    358 /* Figure out how many bytes of the stack's active area have not been
    359    used.  Used for estimating if we are close to overflowing it.  If
    360    the free area is larger than 'limit', just return 'limit'. */
    361 extern SizeT VG_(am_get_VgStack_unused_szB)( const VgStack* stack,
    362                                              SizeT limit );
    363 
    364 // DDD: this is ugly
    365 #if defined(VGO_darwin)
    366 typedef
    367    struct {
    368       Bool   is_added;  // Added or removed seg?
    369       Addr   start;
    370       SizeT  end;
    371       UInt   prot;      // Not used for removed segs.
    372       Off64T offset;    // Not used for removed segs.
    373    }
    374    ChangedSeg;
    375 
    376 extern Bool VG_(get_changed_segments)(
    377       const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css,
    378       Int css_size, /*OUT*/Int* css_used);
    379 #endif
    380 
    381 #if defined(VGO_solaris)
    382 extern Bool VG_(am_search_for_new_segment)(Addr *start, SizeT *size,
    383                                            UInt *prot);
    384 #endif
    385 
    386 #endif   // __PUB_CORE_ASPACEMGR_H
    387 
    388 /*--------------------------------------------------------------------*/
    389 /*--- end                                                          ---*/
    390 /*--------------------------------------------------------------------*/
    391