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 (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) ( 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