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-2010 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 /* Notifies aspacem that the client completed an mmap successfully. 155 The segment array is updated accordingly. If the returned Bool is 156 True, the caller should immediately discard translations from the 157 specified address range. */ 158 extern Bool VG_(am_notify_client_mmap) 159 ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset ); 160 161 /* Notifies aspacem that the client completed a shmat successfully. 162 The segment array is updated accordingly. If the returned Bool is 163 True, the caller should immediately discard translations from the 164 specified address range. */ 165 extern Bool VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ); 166 167 /* Notifies aspacem that an mprotect was completed successfully. The 168 segment array is updated accordingly. Note, as with 169 VG_(am_notify_munmap), it is not the job of this function to reject 170 stupid mprotects, for example the client doing mprotect of 171 non-client areas. Such requests should be intercepted earlier, by 172 the syscall wrapper for mprotect. This function merely records 173 whatever it is told. If the returned Bool is True, the caller 174 should immediately discard translations from the specified address 175 range. */ 176 extern Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot ); 177 178 /* Notifies aspacem that an munmap completed successfully. The 179 segment array is updated accordingly. As with 180 VG_(am_notify_munmap), we merely record the given info, and don't 181 check it for sensibleness. If the returned Bool is True, the 182 caller should immediately discard translations from the specified 183 address range. */ 184 extern Bool VG_(am_notify_munmap)( Addr start, SizeT len ); 185 186 /* Hand a raw mmap to the kernel, without aspacem updating the segment 187 array. THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view 188 of the address space to diverge from that of the kernel. DO NOT 189 USE IT UNLESS YOU UNDERSTAND the request-notify model used by 190 aspacem. In short, DO NOT USE THIS FUNCTION. */ 191 extern SysRes VG_(am_do_mmap_NO_NOTIFY) 192 ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset); 193 194 195 //-------------------------------------------------------------- 196 // Functions pertaining to AIX5-specific notifications. 197 198 /* Describes followup actions that need to be done following a call to 199 VG_(am_aix5_reread_procmap). When acquire==True, the specified 200 code and data segments have been mapped into the process, and so 201 m_debuginfo needs to read info for it; also m_redir needs to know, 202 and the tool needs to be told. When acquire==False, the specified 203 segments have been unloaded and m_debuginfo, m_redir and the tool 204 (and m_transtab?) need to notified appropriately. */ 205 typedef 206 struct { 207 Addr code_start; 208 Word code_len; 209 Addr data_start; 210 Word data_len; 211 UChar* file_name; 212 UChar* mem_name; 213 Bool is_mainexe; 214 Bool acquire; 215 } 216 AixCodeSegChange; 217 218 /* Tell aspacem that /proc/<pid>/map may have changed (eg following 219 __loadx) and so it should be re-read, and the code/data segment 220 list updated accordingly. The resulting array of AixCodeChangeSeg 221 directives are written to 'directives', and the number of entries 222 to *ndirectives. */ 223 extern void VG_(am_aix5_reread_procmap) 224 ( /*OUT*/AixCodeSegChange* directives, /*OUT*/Int* ndirectives ); 225 226 /* Find out the size of the AixCodeSegChange that must be 227 presented to VG_(am_aix5_reread_procmap). */ 228 extern Int VG_(am_aix5_reread_procmap_howmany_directives)(void); 229 230 /* Tell aspacem where the initial client stack is, so that it 231 can later produce a faked-up NSegment in response to 232 VG_(am_find_nsegment) for athat address, if asked. */ 233 extern void VG_(am_aix5_set_initial_client_sp)( Addr ); 234 235 /* The AIX5 aspacem implementation needs to be told when it is and 236 isn't allowed to use sbrk to allocate memory. Hence: */ 237 extern Bool VG_(am_aix5_sbrk_allowed); 238 239 240 //-------------------------------------------------------------- 241 // Dealing with mappings which do not arise directly from the 242 // simulation of the client. These are typically used for 243 // loading the client and building its stack/data segment, before 244 // execution begins. Also for V's own administrative use. 245 246 /* --- --- --- map, unmap, protect --- --- --- */ 247 248 /* Map a file at a fixed address for the client, and update the 249 segment array accordingly. */ 250 extern SysRes VG_(am_mmap_file_fixed_client) 251 ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset ); 252 extern SysRes VG_(am_mmap_named_file_fixed_client) 253 ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset, const HChar *name ); 254 255 /* Map anonymously at a fixed address for the client, and update 256 the segment array accordingly. */ 257 extern SysRes VG_(am_mmap_anon_fixed_client) 258 ( Addr start, SizeT length, UInt prot ); 259 260 261 /* Map anonymously at an unconstrained address for the client, and 262 update the segment array accordingly. */ 263 extern SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot ); 264 265 /* Similarly, acquire new address space for the client but with 266 considerable restrictions on what can be done with it: (1) the 267 actual protections may exceed those stated in 'prot', (2) the 268 area's protections cannot be later changed using any form of 269 mprotect, and (3) the area cannot be freed using any form of 270 munmap. On Linux this behaves the same as 271 VG_(am_mmap_anon_float_client). On AIX5 this *may* allocate memory 272 by using sbrk, so as to make use of large pages on AIX. */ 273 extern SysRes VG_(am_sbrk_anon_float_client) ( SizeT length, Int prot ); 274 275 276 /* Map anonymously at an unconstrained address for V, and update the 277 segment array accordingly. This is fundamentally how V allocates 278 itself more address space when needed. */ 279 extern SysRes VG_(am_mmap_anon_float_valgrind)( SizeT cszB ); 280 281 /* Same comments apply as per VG_(am_sbrk_anon_float_client). On 282 Linux this behaves the same as VG_(am_mmap_anon_float_valgrind). */ 283 extern SysRes VG_(am_sbrk_anon_float_valgrind)( SizeT cszB ); 284 285 286 /* Map a file at an unconstrained address for V, and update the 287 segment array accordingly. This is used by V for transiently 288 mapping in object files to read their debug info. */ 289 extern SysRes VG_(am_mmap_file_float_valgrind) 290 ( SizeT length, UInt prot, Int fd, Off64T offset ); 291 extern SysRes VG_(am_mmap_file_float_valgrind_with_flags) 292 ( SizeT length, UInt prot, UInt flags, Int fd, Off64T offset ); 293 294 /* Unmap the given address range and update the segment array 295 accordingly. This fails if the range isn't valid for the client. 296 If *need_discard is True after a successful return, the caller 297 should immediately discard translations from the specified address 298 range. */ 299 extern SysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard, 300 Addr start, SizeT length ); 301 302 /* Let (start,len) denote an area within a single Valgrind-owned 303 segment (anon or file). Change the ownership of [start, start+len) 304 to the client instead. Fails if (start,len) does not denote a 305 suitable segment. */ 306 extern Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len ); 307 308 /* 'seg' must be NULL or have been obtained from 309 VG_(am_find_nsegment), and still valid. If non-NULL, and if it 310 denotes a SkAnonC (anonymous client mapping) area, set the .isCH 311 (is-client-heap) flag for that area. Otherwise do nothing. 312 (Bizarre interface so that the same code works for both Linux and 313 AIX and does not impose inefficiencies on the Linux version.) */ 314 extern void VG_(am_set_segment_isCH_if_SkAnonC)( NSegment* seg ); 315 316 /* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the 317 segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC 318 segment. */ 319 extern void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( NSegment* ); 320 321 /* --- --- --- reservations --- --- --- */ 322 323 /* Create a reservation from START .. START+LENGTH-1, with the given 324 ShrinkMode. When checking whether the reservation can be created, 325 also ensure that at least abs(EXTRA) extra free bytes will remain 326 above (> 0) or below (< 0) the reservation. 327 328 The reservation will only be created if it, plus the extra-zone, 329 falls entirely within a single free segment. The returned Bool 330 indicates whether the creation succeeded. */ 331 extern Bool VG_(am_create_reservation) 332 ( Addr start, SizeT length, ShrinkMode smode, SSizeT extra ); 333 334 /* Let SEG be an anonymous client mapping. This fn extends the 335 mapping by DELTA bytes, taking the space from a reservation section 336 which must be adjacent. If DELTA is positive, the segment is 337 extended forwards in the address space, and the reservation must be 338 the next one along. If DELTA is negative, the segment is extended 339 backwards in the address space and the reservation must be the 340 previous one. DELTA must be page aligned. abs(DELTA) must not 341 exceed the size of the reservation segment minus one page, that is, 342 the reservation segment after the operation must be at least one 343 page long. */ 344 extern Bool VG_(am_extend_into_adjacent_reservation_client) 345 ( NSegment* seg, SSizeT delta ); 346 347 /* --- --- --- resizing/move a mapping --- --- --- */ 348 349 /* Let SEG be a client mapping (anonymous or file). This fn extends 350 the mapping forwards only by DELTA bytes, and trashes whatever was 351 in the new area. Fails if SEG is not a single client mapping or if 352 the new area is not accessible to the client. Fails if DELTA is 353 not page aligned. *seg is invalid after a successful return. If 354 *need_discard is True after a successful return, the caller should 355 immediately discard translations from the new area. */ 356 extern Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard, 357 NSegment* seg, SizeT delta ); 358 359 /* Remap the old address range to the new address range. Fails if any 360 parameter is not page aligned, if the either size is zero, if any 361 wraparound is implied, if the old address range does not fall 362 entirely within a single segment, if the new address range overlaps 363 with the old one, or if the old address range is not a valid client 364 mapping. If *need_discard is True after a successful return, the 365 caller should immediately discard translations from both specified 366 address ranges. */ 367 extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, 368 Addr old_addr, SizeT old_len, 369 Addr new_addr, SizeT new_len ); 370 371 //-------------------------------------------------------------- 372 // Valgrind (non-client) thread stacks. V itself runs on such 373 // stacks. The address space manager provides and suitably 374 // protects such stacks. 375 376 #if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) 377 # define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages 378 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb 379 #else 380 # define VG_STACK_GUARD_SZB 8192 // 2 pages 381 # define VG_STACK_ACTIVE_SZB (4096 * 256) // 1Mb 382 #endif 383 384 typedef 385 struct { 386 HChar bytes[VG_STACK_GUARD_SZB 387 + VG_STACK_ACTIVE_SZB 388 + VG_STACK_GUARD_SZB]; 389 } 390 VgStack; 391 392 393 /* Allocate and initialise a VgStack (anonymous client space). 394 Protect the stack active area and the guard areas appropriately. 395 Returns NULL on failure, else the address of the bottom of the 396 stack. On success, also sets *initial_sp to what the stack pointer 397 should be set to. */ 398 399 extern VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp ); 400 401 /* Figure out how many bytes of the stack's active area have not been 402 used. Used for estimating if we are close to overflowing it. If 403 the free area is larger than 'limit', just return 'limit'. */ 404 extern SizeT VG_(am_get_VgStack_unused_szB)( VgStack* stack, SizeT limit ); 405 406 // DDD: this is ugly 407 #if defined(VGO_darwin) 408 typedef 409 struct { 410 Bool is_added; // Added or removed seg? 411 Addr start; 412 SizeT end; 413 UInt prot; // Not used for removed segs. 414 Off64T offset; // Not used for removed segs. 415 } 416 ChangedSeg; 417 418 extern Bool VG_(get_changed_segments)( 419 const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css, 420 Int css_size, /*OUT*/Int* css_used); 421 #endif 422 423 #endif // __PUB_CORE_ASPACEMGR_H 424 425 /*--------------------------------------------------------------------*/ 426 /*--- end ---*/ 427 /*--------------------------------------------------------------------*/ 428