--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- The address space manager. pub_core_aspacemgr.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2010 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_ASPACEMGR_H
+#define __PUB_CORE_ASPACEMGR_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module deals with management of the entire process
+// address space. Almost everything depends upon it, including dynamic
+// memory management. Hence this module is almost completely
+// standalone; the only module it uses is m_debuglog. DO NOT CHANGE
+// THIS.
+//--------------------------------------------------------------------
+
+#include "pub_tool_aspacemgr.h"
+
+//--------------------------------------------------------------
+// Definition of address-space segments
+
+/* types SegKind, ShrinkMode and NSegment are described in
+ the tool-visible header file, not here. */
+
+
+//--------------------------------------------------------------
+// Initialisation
+
+/* Initialise the address space manager, setting up the initial
+ segment list, and reading /proc/self/maps into it. This must
+ be called before any other function.
+
+ Takes a pointer to the SP at the time V gained control. This is
+ taken to be the highest usable address (more or less). Based on
+ that (and general consultation of tea leaves, etc) return a
+ suggested end address for the client's stack. */
+extern Addr VG_(am_startup) ( Addr sp_at_startup );
+
+
+//--------------------------------------------------------------
+// Querying current status
+
+/* Finds the segment containing 'a'. Only returns file/anon/resvn
+ segments. This returns a 'NSegment const *' - a pointer to
+ readonly data. */
+// Is in tool-visible header file.
+// extern NSegment const * VG_(am_find_nsegment) ( Addr a );
+
+/* Find the next segment along from 'here', if it is a file/anon/resvn
+ segment. */
+extern NSegment const* VG_(am_next_nsegment) ( NSegment* here, Bool fwds );
+
+/* Is the area [start .. start+len-1] validly accessible by the
+ client with at least the permissions 'prot' ? To find out
+ simply if said area merely belongs to the client, pass
+ VKI_PROT_NONE as 'prot'. Will return False if any part of the
+ area does not belong to the client or does not have at least
+ the stated permissions. */
+// Is in tool-visible header file.
+// extern Bool VG_(am_is_valid_for_client)
+// ( Addr start, SizeT len, UInt prot );
+
+/* Variant of VG_(am_is_valid_for_client) which allows free areas to
+ be consider part of the client's addressable space. It also
+ considers reservations to be allowable, since from the client's
+ point of view they don't exist. */
+extern Bool VG_(am_is_valid_for_client_or_free_or_resvn)
+ ( Addr start, SizeT len, UInt prot );
+
+/* Trivial fn: return the total amount of space in anonymous mappings,
+ both for V and the client. Is used for printing stats in
+ out-of-memory messages. */
+extern ULong VG_(am_get_anonsize_total)( void );
+
+/* Show the segment array on the debug log, at given loglevel. */
+extern void VG_(am_show_nsegments) ( Int logLevel, HChar* who );
+
+/* Get the filename corresponding to this segment, if known and if it
+ has one. The returned name's storage cannot be assumed to be
+ persistent, so the caller should immediately copy the name
+ elsewhere. This may return NULL if the file name is not known or
+ for arbitrary other implementation-dependent reasons, so callers
+ need to be able to handle a NULL return value. */
+// Is in tool-visible header file.
+// extern HChar* VG_(am_get_filename)( NSegment* );
+
+/* VG_(am_get_segment_starts) is also part of this section, but its
+ prototype is tool-visible, hence not in this header file. */
+
+/* Sanity check: check that Valgrind and the kernel agree on the
+ address space layout. Prints offending segments and call point if
+ a discrepancy is detected, but does not abort the system. Returned
+ Bool is False if a discrepancy was found. */
+
+extern Bool VG_(am_do_sync_check) ( const HChar* fn,
+ const HChar* file, Int line );
+
+//--------------------------------------------------------------
+// Functions pertaining to the central query-notify mechanism
+// used to handle mmap/munmap/mprotect resulting from client
+// syscalls.
+
+/* Describes a request for VG_(am_get_advisory). */
+typedef
+ struct {
+ enum { MFixed, MHint, MAny } rkind;
+ Addr start;
+ Addr len;
+ }
+ MapRequest;
+
+/* Query aspacem to ask where a mapping should go. On success, the
+ advised placement is returned, and *ok is set to True. On failure,
+ zero is returned and *ok is set to False. Note that *ok must be
+ consulted by the caller to establish success or failure; that
+ cannot be established reliably from the returned value. If *ok is
+ set to False, it means aspacem has vetoed the mapping, and so the
+ caller should not proceed with it. */
+extern Addr VG_(am_get_advisory)
+ ( MapRequest* req, Bool forClient, /*OUT*/Bool* ok );
+
+/* Convenience wrapper for VG_(am_get_advisory) for client floating or
+ fixed requests. If start is zero, a floating request is issued; if
+ nonzero, a fixed request at that address is issued. Same comments
+ about return values apply. */
+extern Addr VG_(am_get_advisory_client_simple)
+ ( Addr start, SizeT len, /*OUT*/Bool* ok );
+
+/* Notifies aspacem that the client completed an mmap successfully.
+ The segment array is updated accordingly. If the returned Bool is
+ True, the caller should immediately discard translations from the
+ specified address range. */
+extern Bool VG_(am_notify_client_mmap)
+ ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset );
+extern Bool VG_(am_notify_valgrind_mmap)
+ ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset );
+
+/* Notifies aspacem that the client completed a shmat successfully.
+ The segment array is updated accordingly. If the returned Bool is
+ True, the caller should immediately discard translations from the
+ specified address range. */
+extern Bool VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot );
+
+/* Notifies aspacem that an mprotect was completed successfully. The
+ segment array is updated accordingly. Note, as with
+ VG_(am_notify_munmap), it is not the job of this function to reject
+ stupid mprotects, for example the client doing mprotect of
+ non-client areas. Such requests should be intercepted earlier, by
+ the syscall wrapper for mprotect. This function merely records
+ whatever it is told. If the returned Bool is True, the caller
+ should immediately discard translations from the specified address
+ range. */
+extern Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot );
+
+/* Notifies aspacem that an munmap completed successfully. The
+ segment array is updated accordingly. As with
+ VG_(am_notify_munmap), we merely record the given info, and don't
+ check it for sensibleness. If the returned Bool is True, the
+ caller should immediately discard translations from the specified
+ address range. */
+extern Bool VG_(am_notify_munmap)( Addr start, SizeT len );
+
+/* Hand a raw mmap to the kernel, without aspacem updating the segment
+ array. THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view
+ of the address space to diverge from that of the kernel. DO NOT
+ USE IT UNLESS YOU UNDERSTAND the request-notify model used by
+ aspacem. In short, DO NOT USE THIS FUNCTION. */
+extern SysRes VG_(am_do_mmap_NO_NOTIFY)
+ ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset);
+
+
+//--------------------------------------------------------------
+// Functions pertaining to AIX5-specific notifications.
+
+/* Describes followup actions that need to be done following a call to
+ VG_(am_aix5_reread_procmap). When acquire==True, the specified
+ code and data segments have been mapped into the process, and so
+ m_debuginfo needs to read info for it; also m_redir needs to know,
+ and the tool needs to be told. When acquire==False, the specified
+ segments have been unloaded and m_debuginfo, m_redir and the tool
+ (and m_transtab?) need to notified appropriately. */
+typedef
+ struct {
+ Addr code_start;
+ Word code_len;
+ Addr data_start;
+ Word data_len;
+ UChar* file_name;
+ UChar* mem_name;
+ Bool is_mainexe;
+ Bool acquire;
+ }
+ AixCodeSegChange;
+
+/* Tell aspacem that /proc/<pid>/map may have changed (eg following
+ __loadx) and so it should be re-read, and the code/data segment
+ list updated accordingly. The resulting array of AixCodeChangeSeg
+ directives are written to 'directives', and the number of entries
+ to *ndirectives. */
+extern void VG_(am_aix5_reread_procmap)
+ ( /*OUT*/AixCodeSegChange* directives, /*OUT*/Int* ndirectives );
+
+/* Find out the size of the AixCodeSegChange that must be
+ presented to VG_(am_aix5_reread_procmap). */
+extern Int VG_(am_aix5_reread_procmap_howmany_directives)(void);
+
+/* Tell aspacem where the initial client stack is, so that it
+ can later produce a faked-up NSegment in response to
+ VG_(am_find_nsegment) for athat address, if asked. */
+extern void VG_(am_aix5_set_initial_client_sp)( Addr );
+
+/* The AIX5 aspacem implementation needs to be told when it is and
+ isn't allowed to use sbrk to allocate memory. Hence: */
+extern Bool VG_(am_aix5_sbrk_allowed);
+
+
+//--------------------------------------------------------------
+// Dealing with mappings which do not arise directly from the
+// simulation of the client. These are typically used for
+// loading the client and building its stack/data segment, before
+// execution begins. Also for V's own administrative use.
+
+/* --- --- --- map, unmap, protect --- --- --- */
+
+/* Map a file at a fixed address for the client, and update the
+ segment array accordingly. */
+extern SysRes VG_(am_mmap_file_fixed_client)
+ ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset );
+extern SysRes VG_(am_mmap_named_file_fixed_client)
+ ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset, const HChar *name );
+
+/* Map anonymously at a fixed address for the client, and update
+ the segment array accordingly. */
+extern SysRes VG_(am_mmap_anon_fixed_client)
+ ( Addr start, SizeT length, UInt prot );
+
+
+/* Map anonymously at an unconstrained address for the client, and
+ update the segment array accordingly. */
+extern SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot );
+
+/* Similarly, acquire new address space for the client but with
+ considerable restrictions on what can be done with it: (1) the
+ actual protections may exceed those stated in 'prot', (2) the
+ area's protections cannot be later changed using any form of
+ mprotect, and (3) the area cannot be freed using any form of
+ munmap. On Linux this behaves the same as
+ VG_(am_mmap_anon_float_client). On AIX5 this *may* allocate memory
+ by using sbrk, so as to make use of large pages on AIX. */
+extern SysRes VG_(am_sbrk_anon_float_client) ( SizeT length, Int prot );
+
+
+/* Map anonymously at an unconstrained address for V, and update the
+ segment array accordingly. This is fundamentally how V allocates
+ itself more address space when needed. */
+extern SysRes VG_(am_mmap_anon_float_valgrind)( SizeT cszB );
+
+/* Same comments apply as per VG_(am_sbrk_anon_float_client). On
+ Linux this behaves the same as VG_(am_mmap_anon_float_valgrind). */
+extern SysRes VG_(am_sbrk_anon_float_valgrind)( SizeT cszB );
+
+
+/* Map a file at an unconstrained address for V, and update the
+ segment array accordingly. This is used by V for transiently
+ mapping in object files to read their debug info. */
+extern SysRes VG_(am_mmap_file_float_valgrind)
+ ( SizeT length, UInt prot, Int fd, Off64T offset );
+
+/* Unmap the given address range and update the segment array
+ accordingly. This fails if the range isn't valid for the client.
+ If *need_discard is True after a successful return, the caller
+ should immediately discard translations from the specified address
+ range. */
+extern SysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard,
+ Addr start, SizeT length );
+
+/* Let (start,len) denote an area within a single Valgrind-owned
+ segment (anon or file). Change the ownership of [start, start+len)
+ to the client instead. Fails if (start,len) does not denote a
+ suitable segment. */
+extern Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len );
+
+/* 'seg' must be NULL or have been obtained from
+ VG_(am_find_nsegment), and still valid. If non-NULL, and if it
+ denotes a SkAnonC (anonymous client mapping) area, set the .isCH
+ (is-client-heap) flag for that area. Otherwise do nothing.
+ (Bizarre interface so that the same code works for both Linux and
+ AIX and does not impose inefficiencies on the Linux version.) */
+extern void VG_(am_set_segment_isCH_if_SkAnonC)( NSegment* seg );
+
+/* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the
+ segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC
+ segment. */
+extern void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( NSegment* );
+
+/* --- --- --- reservations --- --- --- */
+
+/* Create a reservation from START .. START+LENGTH-1, with the given
+ ShrinkMode. When checking whether the reservation can be created,
+ also ensure that at least abs(EXTRA) extra free bytes will remain
+ above (> 0) or below (< 0) the reservation.
+
+ The reservation will only be created if it, plus the extra-zone,
+ falls entirely within a single free segment. The returned Bool
+ indicates whether the creation succeeded. */
+extern Bool VG_(am_create_reservation)
+ ( Addr start, SizeT length, ShrinkMode smode, SSizeT extra );
+
+/* Let SEG be an anonymous client mapping. This fn extends the
+ mapping by DELTA bytes, taking the space from a reservation section
+ which must be adjacent. If DELTA is positive, the segment is
+ extended forwards in the address space, and the reservation must be
+ the next one along. If DELTA is negative, the segment is extended
+ backwards in the address space and the reservation must be the
+ previous one. DELTA must be page aligned. abs(DELTA) must not
+ exceed the size of the reservation segment minus one page, that is,
+ the reservation segment after the operation must be at least one
+ page long. */
+extern Bool VG_(am_extend_into_adjacent_reservation_client)
+ ( NSegment* seg, SSizeT delta );
+
+/* --- --- --- resizing/move a mapping --- --- --- */
+
+/* Let SEG be a client mapping (anonymous or file). This fn extends
+ the mapping forwards only by DELTA bytes, and trashes whatever was
+ in the new area. Fails if SEG is not a single client mapping or if
+ the new area is not accessible to the client. Fails if DELTA is
+ not page aligned. *seg is invalid after a successful return. If
+ *need_discard is True after a successful return, the caller should
+ immediately discard translations from the new area. */
+extern Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard,
+ NSegment* seg, SizeT delta );
+
+/* Remap the old address range to the new address range. Fails if any
+ parameter is not page aligned, if the either size is zero, if any
+ wraparound is implied, if the old address range does not fall
+ entirely within a single segment, if the new address range overlaps
+ with the old one, or if the old address range is not a valid client
+ mapping. If *need_discard is True after a successful return, the
+ caller should immediately discard translations from both specified
+ address ranges. */
+extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
+ Addr old_addr, SizeT old_len,
+ Addr new_addr, SizeT new_len );
+
+//--------------------------------------------------------------
+// Valgrind (non-client) thread stacks. V itself runs on such
+// stacks. The address space manager provides and suitably
+// protects such stacks.
+
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+# define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages
+# define VG_STACK_ACTIVE_SZB 131072 // 2 or 32 pages
+#else
+# define VG_STACK_GUARD_SZB 8192 // 2 pages
+# define VG_STACK_ACTIVE_SZB 65536 // 16 pages
+#endif
+
+typedef
+ struct {
+ HChar bytes[VG_STACK_GUARD_SZB
+ + VG_STACK_ACTIVE_SZB
+ + VG_STACK_GUARD_SZB];
+ }
+ VgStack;
+
+
+/* Allocate and initialise a VgStack (anonymous client space).
+ Protect the stack active area and the guard areas appropriately.
+ Returns NULL on failure, else the address of the bottom of the
+ stack. On success, also sets *initial_sp to what the stack pointer
+ should be set to. */
+
+extern VgStack* VG_(am_alloc_VgStack)( /*OUT*/Addr* initial_sp );
+
+/* Figure out how many bytes of the stack's active area have not
+ been used. Used for estimating if we are close to overflowing it. */
+
+extern Int VG_(am_get_VgStack_unused_szB)( VgStack* stack );
+
+// DDD: this is ugly
+#if defined(VGO_darwin)
+typedef
+ struct {
+ Bool is_added; // Added or removed seg?
+ Addr start;
+ SizeT end;
+ UInt prot; // Not used for removed segs.
+ Off64T offset; // Not used for removed segs.
+ }
+ ChangedSeg;
+
+extern Bool VG_(get_changed_segments)(
+ const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css,
+ Int css_size, /*OUT*/Int* css_used);
+#endif
+
+#endif // __PUB_CORE_ASPACEMGR_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/