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