195af4ce809c85e3659843aa4156089c80b2b4353florian/* -*- mode: C; c-basic-offset: 3; -*- */
2de4a1d01951937632098a6cda45859afa587a06fsewardj
3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
455f9d1a56f3542c68f5b24006c14b1f9aaefff6fsewardj/*--- The address space manager: segment initialisation and        ---*/
555f9d1a56f3542c68f5b24006c14b1f9aaefff6fsewardj/*--- tracking, stack operations                                   ---*/
6297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj/*---                                                              ---*/
7da9420ce499f657b2cb66bf1b5e2a6c5461bb9d8florian/*--- Implementation for Linux (and Darwin!)     aspacemgr-linux.c ---*/
8de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
9de4a1d01951937632098a6cda45859afa587a06fsewardj
10de4a1d01951937632098a6cda45859afa587a06fsewardj/*
11b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   This file is part of Valgrind, a dynamic binary instrumentation
12b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   framework.
13de4a1d01951937632098a6cda45859afa587a06fsewardj
14ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2000-2017 Julian Seward
15de4a1d01951937632098a6cda45859afa587a06fsewardj      jseward@acm.org
16de4a1d01951937632098a6cda45859afa587a06fsewardj
17de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is free software; you can redistribute it and/or
18de4a1d01951937632098a6cda45859afa587a06fsewardj   modify it under the terms of the GNU General Public License as
19de4a1d01951937632098a6cda45859afa587a06fsewardj   published by the Free Software Foundation; either version 2 of the
20de4a1d01951937632098a6cda45859afa587a06fsewardj   License, or (at your option) any later version.
21de4a1d01951937632098a6cda45859afa587a06fsewardj
22de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is distributed in the hope that it will be useful, but
23de4a1d01951937632098a6cda45859afa587a06fsewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
24de4a1d01951937632098a6cda45859afa587a06fsewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25de4a1d01951937632098a6cda45859afa587a06fsewardj   General Public License for more details.
26de4a1d01951937632098a6cda45859afa587a06fsewardj
27de4a1d01951937632098a6cda45859afa587a06fsewardj   You should have received a copy of the GNU General Public License
28de4a1d01951937632098a6cda45859afa587a06fsewardj   along with this program; if not, write to the Free Software
29de4a1d01951937632098a6cda45859afa587a06fsewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30de4a1d01951937632098a6cda45859afa587a06fsewardj   02111-1307, USA.
31de4a1d01951937632098a6cda45859afa587a06fsewardj
32e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   The GNU General Public License is contained in the file COPYING.
33de4a1d01951937632098a6cda45859afa587a06fsewardj*/
34de4a1d01951937632098a6cda45859afa587a06fsewardj
358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
368b68b64759254d514d98328c496cbd88cde4c9a5njn
37297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj/* *************************************************************
38297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   DO NOT INCLUDE ANY OTHER FILES HERE.
39297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   ADD NEW INCLUDES ONLY TO priv_aspacemgr.h
40297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   AND THEN ONLY AFTER READING DIRE WARNINGS THERE TOO.
41297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   ************************************************************* */
4255f9d1a56f3542c68f5b24006c14b1f9aaefff6fsewardj
43297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj#include "priv_aspacemgr.h"
44870f7451dcc5ff1ec6c84e8bb2832bd5834459c2bart#include "config.h"
4504e1698d9f92df36742be7c1e0fefb9af1c5b1bdnjn
4604e1698d9f92df36742be7c1e0fefb9af1c5b1bdnjn
47aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj/* Note: many of the exported functions implemented below are
48aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj   described more fully in comments in pub_core_aspacemgr.h.
49aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj*/
50aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj
51aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj
5245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
5345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
54a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj/*--- Overview.                                                 ---*/
55a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj/*---                                                           ---*/
56a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj/*-----------------------------------------------------------------*/
57a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
58a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj/* Purpose
59a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   ~~~~~~~
60a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   The purpose of the address space manager (aspacem) is:
61a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
62a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   (1) to record the disposition of all parts of the process' address
63a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj       space at all times.
64a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
65a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   (2) to the extent that it can, influence layout in ways favourable
66a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj       to our purposes.
67a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
68a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   It is important to appreciate that whilst it can and does attempt
69a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   to influence layout, and usually succeeds, it isn't possible to
70a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   impose absolute control: in the end, the kernel is the final
71a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   arbiter, and can always bounce our requests.
72a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
73a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   Strategy
74a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   ~~~~~~~~
75a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   The strategy is therefore as follows:
76a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
77a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * Track ownership of mappings.  Each one can belong either to
78a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     Valgrind or to the client.
79a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
80a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * Try to place the client's fixed and hinted mappings at the
81a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     requested addresses.  Fixed mappings are allowed anywhere except
82a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     in areas reserved by Valgrind; the client can trash its own
83a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     mappings if it wants.  Hinted mappings are allowed providing they
84a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     fall entirely in free areas; if not, they will be placed by
85a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     aspacem in a free area.
86a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
87a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * Anonymous mappings are allocated so as to keep Valgrind and
88a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     client areas widely separated when possible.  If address space
89a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     runs low, then they may become intermingled: aspacem will attempt
90a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     to use all possible space.  But under most circumstances lack of
91a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     address space is not a problem and so the areas will remain far
92a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     apart.
93a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
94a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     Searches for client space start at aspacem_cStart and will wrap
95a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     around the end of the available space if needed.  Searches for
96a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     Valgrind space start at aspacem_vStart and will also wrap around.
97a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     Because aspacem_cStart is approximately at the start of the
98a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     available space and aspacem_vStart is approximately in the
99a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     middle, for the most part the client anonymous mappings will be
100a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     clustered towards the start of available space, and Valgrind ones
101a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     in the middle.
102a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
1038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     On Solaris, searches for client space start at (aspacem_vStart - 1)
1048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     and for Valgrind space start at (aspacem_maxAddr - 1) and go backwards.
1058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     This simulates what kernel does - brk limit grows from bottom and mmap'ed
1068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     objects from top. It is in contrary with Linux where data segment
1078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     and mmap'ed objects grow from bottom (leading to early data segment
1088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     exhaustion for tools which do not use m_replacemalloc). While Linux glibc
1098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     can cope with this problem by employing mmap, Solaris libc treats inability
1108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     to grow brk limit as a hard failure.
1118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
112a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     The available space is delimited by aspacem_minAddr and
113a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     aspacem_maxAddr.  aspacem is flexible and can operate with these
114a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     at any (sane) setting.  For 32-bit Linux, aspacem_minAddr is set
115a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     to some low-ish value at startup (64M) and aspacem_maxAddr is
116a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     derived from the stack pointer at system startup.  This seems a
117a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     reliable way to establish the initial boundaries.
118e4d78123089e55bec64a4f848bdc09556192e259philippe     A command line option allows to change the value of aspacem_minAddr,
119e4d78123089e55bec64a4f848bdc09556192e259philippe     so as to allow memory hungry applications to use the lowest
120e4d78123089e55bec64a4f848bdc09556192e259philippe     part of the memory.
121a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
122a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     64-bit Linux is similar except for the important detail that the
123e06727f0a4f01862c908ce95eb3af4e401d9fa9dsewardj     upper boundary is set to 64G.  The reason is so that all
124a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     anonymous mappings (basically all client data areas) are kept
125e06727f0a4f01862c908ce95eb3af4e401d9fa9dsewardj     below 64G, since that is the maximum range that memcheck can
126a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     track shadow memory using a fast 2-level sparse array.  It can go
127e06727f0a4f01862c908ce95eb3af4e401d9fa9dsewardj     beyond that but runs much more slowly.  The 64G limit is
128a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     arbitrary and is trivially changed.  So, with the current
129a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     settings, programs on 64-bit Linux will appear to run out of
130e06727f0a4f01862c908ce95eb3af4e401d9fa9dsewardj     address space and presumably fail at the 64G limit.  Given the
131e06727f0a4f01862c908ce95eb3af4e401d9fa9dsewardj     considerable space overhead of Memcheck, that means you should be
132e06727f0a4f01862c908ce95eb3af4e401d9fa9dsewardj     able to memcheckify programs that use up to about 32G natively.
133a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
134a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   Note that the aspacem_minAddr/aspacem_maxAddr limits apply only to
135a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   anonymous mappings.  The client can still do fixed and hinted maps
136a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   at any addresses provided they do not overlap Valgrind's segments.
137a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   This makes Valgrind able to load prelinked .so's at their requested
138a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   addresses on 64-bit platforms, even if they are very high (eg,
139a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   112TB).
140a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
141a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   At startup, aspacem establishes the usable limits, and advises
142a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   m_main to place the client stack at the top of the range, which on
143a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   a 32-bit machine will be just below the real initial stack.  One
144a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   effect of this is that self-hosting sort-of works, because an inner
145a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   valgrind will then place its client's stack just below its own
146a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   initial stack.
147a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
148a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   The segment array and segment kinds
149a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
150a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   The central data structure is the segment array (segments[0
151a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   .. nsegments_used-1]).  This covers the entire address space in
152a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   order, giving account of every byte of it.  Free spaces are
153a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   represented explicitly as this makes many operations simpler.
154a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   Mergeable adjacent segments are aggressively merged so as to create
155a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   a "normalised" representation (preen_nsegments).
156a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
157a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   There are 7 (mutually-exclusive) segment kinds, the meaning of
158a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   which is important:
159a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
160a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkFree: a free space, which may be allocated either to Valgrind (V)
161a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj      or the client (C).
162a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
163a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkAnonC: an anonymous mapping belonging to C.  For these, aspacem
164a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj      tracks a boolean indicating whether or not is is part of the
165a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj      client's heap area (can't remember why).
166a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
167a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkFileC: a file mapping belonging to C.
168a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
169a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkShmC: a shared memory segment belonging to C.
170a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
171a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkAnonV: an anonymous mapping belonging to V.  These cover all V's
172a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj      dynamic memory needs, including non-client malloc/free areas,
173a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj      shadow memory, and the translation cache.
174a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
175a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkFileV: a file mapping belonging to V.  As far as I know these are
176a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj      only created transiently for the purposes of reading debug info.
177a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
178a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   SkResvn: a reservation segment.
179a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
180a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   These are mostly straightforward.  Reservation segments have some
181a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   subtlety, however.
182a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
183a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   A reservation segment is unmapped from the kernel's point of view,
184a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   but is an area in which aspacem will not create anonymous maps
185a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   (either Vs or Cs).  The idea is that we will try to keep it clear
186a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   when the choice to do so is ours.  Reservation segments are
187a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   'invisible' from the client's point of view: it may choose to park
188a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   a fixed mapping in the middle of one, and that's just tough -- we
189a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   can't do anything about that.  From the client's perspective
190a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   reservations are semantically equivalent to (although
191a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   distinguishable from, if it makes enquiries) free areas.
192a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
193a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   Reservations are a primitive mechanism provided for whatever
194a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   purposes the rest of the system wants.  Currently they are used to
195a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   reserve the expansion space into which a growdown stack is
196a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   expanded, and into which the data segment is extended.  Note,
197a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   though, those uses are entirely external to this module, which only
198a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   supplies the primitives.
199a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
200a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   Reservations may be shrunk in order that an adjoining anonymous
201a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   mapping may be extended.  This makes dataseg/stack expansion work.
202a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   A reservation may not be shrunk below one page.
203a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
204a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   The advise/notify concept
205a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   ~~~~~~~~~~~~~~~~~~~~~~~~~
206a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   All mmap-related calls must be routed via aspacem.  Calling
207a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   sys_mmap directly from the rest of the system is very dangerous
208a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   because aspacem's data structures will become out of date.
209a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
210a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   The fundamental mode of operation of aspacem is to support client
211a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   mmaps.  Here's what happens (in ML_(generic_PRE_sys_mmap)):
212a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
213a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * m_syswrap intercepts the mmap call.  It examines the parameters
214a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     and identifies the requested placement constraints.  There are
215a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     three possibilities: no constraint (MAny), hinted (MHint, "I
216a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     prefer X but will accept anything"), and fixed (MFixed, "X or
217a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     nothing").
218a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
219a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * This request is passed to VG_(am_get_advisory).  This decides on
220a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     a placement as described in detail in Strategy above.  It may
221a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     also indicate that the map should fail, because it would trash
222a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     one of Valgrind's areas, which would probably kill the system.
223a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
224a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * Control returns to the wrapper.  If VG_(am_get_advisory) has
225a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     declared that the map should fail, then it must be made to do so.
226a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     Usually, though, the request is considered acceptable, in which
227a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     case an "advised" address is supplied.  The advised address
228a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     replaces the original address supplied by the client, and
229a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     MAP_FIXED is set.
230a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
231a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     Note at this point that although aspacem has been asked for
232a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     advice on where to place the mapping, no commitment has yet been
233a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     made by either it or the kernel.
234a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
235a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * The adjusted request is handed off to the kernel.
236a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
237a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj   * The kernel's result is examined.  If the map succeeded, aspacem
238a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     is told of the outcome (VG_(am_notify_client_mmap)), so it can
239a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj     update its records accordingly.
240a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
241a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  This then is the central advise-notify idiom for handling client
242a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  mmap/munmap/mprotect/shmat:
243a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
244a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  * ask aspacem for an advised placement (or a veto)
245a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
246a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  * if not vetoed, hand request to kernel, using the advised placement
247a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
248a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  * examine result, and if successful, notify aspacem of the result.
249a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
250a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  There are also many convenience functions, eg
251a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  VG_(am_mmap_anon_fixed_client), which do both phases entirely within
252a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  aspacem.
253a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
254a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  To debug all this, a sync-checker is provided.  It reads
255a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  /proc/self/maps, compares what it sees with aspacem's records, and
256a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  complains if there is a difference.  --sanity-level=3 runs it before
257a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  and after each syscall, which is a powerful, if slow way of finding
258a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj  buggy syscall wrappers.
2594f3ef1ff3af3c637f38d4352f38581effba95c4esewardj
2604f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  Loss of pointercheck
2614f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  ~~~~~~~~~~~~~~~~~~~~
2624f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  Up to and including Valgrind 2.4.1, x86 segmentation was used to
263ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes  enforce separation of V and C, so that wild writes by C could not
2644f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  trash V.  This got called "pointercheck".  Unfortunately, the new
2654f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  more flexible memory layout, plus the need to be portable across
2664f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  different architectures, means doing this in hardware is no longer
2674f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  viable, and doing it in software is expensive.  So at the moment we
2684f3ef1ff3af3c637f38d4352f38581effba95c4esewardj  don't do it at all.
269a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj*/
270a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
271a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj
272a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj/*-----------------------------------------------------------------*/
273a07dce4dd13dcdc96ad5dc1c7d7b0f8a1bbac2e6sewardj/*---                                                           ---*/
27445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- The Address Space Manager's state.                        ---*/
27545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
27645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
27704e1698d9f92df36742be7c1e0fefb9af1c5b1bdnjn
27845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* ------ start of STATE for the address-space manager ------ */
279b69f7c12ae343c3435b4b3bd0aa372144bdf5977njn
280f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj/* Max number of segments we can track.  On Android, virtual address
281f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj   space is limited, so keep a low limit -- 5000 x sizef(NSegment) is
282f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj   360KB. */
28326ed419d60369d0545510eba0832566e24452e1esewardj#if defined(VGPV_arm_linux_android) \
28426ed419d60369d0545510eba0832566e24452e1esewardj    || defined(VGPV_x86_linux_android) \
28526ed419d60369d0545510eba0832566e24452e1esewardj    || defined(VGPV_mips32_linux_android) \
28626ed419d60369d0545510eba0832566e24452e1esewardj    || defined(VGPV_arm64_linux_android)
287f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj# define VG_N_SEGMENTS 5000
288f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj#else
289f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj# define VG_N_SEGMENTS 30000
290f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj#endif
291f049d1dc2a4df13444555135a59a78c56fc76b2fsewardj
29245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Array [0 .. nsegments_used-1] of all mappings. */
29345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Sorted by .addr field. */
29445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* I: len may not be zero. */
29545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* I: overlapping segments are not allowed. */
29645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* I: the segments cover the entire address space precisely. */
29745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Each segment can optionally hold an index into the filename table. */
29845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
29945f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic NSegment nsegments[VG_N_SEGMENTS];
30045f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Int      nsegments_used = 0;
30145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
30245f4e7c91119c7d01a59f5e827c67841632c9314sewardj#define Addr_MIN ((Addr)0)
30345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#define Addr_MAX ((Addr)(-1ULL))
30445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
30545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Limits etc */
30645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
307e4d78123089e55bec64a4f848bdc09556192e259philippe
308e4d78123089e55bec64a4f848bdc09556192e259philippeAddr VG_(clo_aspacem_minAddr)
3098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_linux)
3108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   = (Addr) 0x04000000; // 64M
3118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(VGO_darwin)
312e4d78123089e55bec64a4f848bdc09556192e259philippe# if VG_WORDSIZE == 4
313e4d78123089e55bec64a4f848bdc09556192e259philippe   = (Addr) 0x00001000;
314e4d78123089e55bec64a4f848bdc09556192e259philippe# else
315e4d78123089e55bec64a4f848bdc09556192e259philippe   = (Addr) 0x100000000;  // 4GB page zero
316e4d78123089e55bec64a4f848bdc09556192e259philippe# endif
3178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(VGO_solaris)
3188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   = (Addr) 0x00100000; // 1MB
319e4d78123089e55bec64a4f848bdc09556192e259philippe#else
320e4d78123089e55bec64a4f848bdc09556192e259philippe#endif
321e4d78123089e55bec64a4f848bdc09556192e259philippe
322e4d78123089e55bec64a4f848bdc09556192e259philippe
32345f4e7c91119c7d01a59f5e827c67841632c9314sewardj// The smallest address that aspacem will try to allocate
32445f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Addr aspacem_minAddr = 0;
32545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
32645f4e7c91119c7d01a59f5e827c67841632c9314sewardj// The largest address that aspacem will try to allocate
32745f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Addr aspacem_maxAddr = 0;
32845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
32945f4e7c91119c7d01a59f5e827c67841632c9314sewardj// Where aspacem will start looking for client space
33045f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Addr aspacem_cStart = 0;
33145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
33245f4e7c91119c7d01a59f5e827c67841632c9314sewardj// Where aspacem will start looking for Valgrind space
33345f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Addr aspacem_vStart = 0;
33445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
33545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
33645f4e7c91119c7d01a59f5e827c67841632c9314sewardj#define AM_SANITY_CHECK                                      \
33745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   do {                                                      \
338a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      if (VG_(clo_sanity_level) >= 3)                        \
33945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         aspacem_assert(VG_(am_do_sync_check)                \
34045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            (__PRETTY_FUNCTION__,__FILE__,__LINE__));        \
34145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } while (0)
34245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
34345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* ------ end of STATE for the address-space manager ------ */
34445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
345cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* ------ Forwards decls ------ */
346a364d119b3847143d804e388d7a37c2c82be93bfsewardjinline
34745f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Int  find_nsegment_idx ( Addr a );
34845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
349cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic void parse_procselfmaps (
350cb249ab3febb3757a0b0582be21952efacf415e5sewardj      void (*record_mapping)( Addr addr, SizeT len, UInt prot,
351c4431bfe04c7490ea2d74939d222d87f13f30960njn                              ULong dev, ULong ino, Off64T offset,
352dbb3584f591710a15a437918c0fc27e300993566florian                              const HChar* filename ),
353cb249ab3febb3757a0b0582be21952efacf415e5sewardj      void (*record_gap)( Addr addr, SizeT len )
354cb249ab3febb3757a0b0582be21952efacf415e5sewardj   );
355cb249ab3febb3757a0b0582be21952efacf415e5sewardj
35638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/* ----- Hacks to do with the "commpage" on arm-linux ----- */
35738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/* Not that I have anything against the commpage per se.  It's just
35838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   that it's not listed in /proc/self/maps, which is a royal PITA --
359f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   we have to fake it up, in parse_procselfmaps.
360f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj
361f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   But note also bug 254556 comment #2: this is now fixed in newer
362f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   kernels -- it is listed as a "[vectors]" entry.  Presumably the
363f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   fake entry made here duplicates the [vectors] entry, and so, if at
364f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   some point in the future, we can stop supporting buggy kernels,
365f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   then this kludge can be removed entirely, since the procmap parser
366f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj   below will read that entry in the normal way. */
36738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#if defined(VGP_arm_linux)
36838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  define ARM_LINUX_FAKE_COMMPAGE_START 0xFFFF0000
369f90dcbc6bfab3c26fa1802c1e307d4673a1412e5sewardj#  define ARM_LINUX_FAKE_COMMPAGE_END1  0xFFFF1000
37038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#endif
37138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
37245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
373548be6d64c58729588a559b1512ad7625bc1b86esewardj
37445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
37545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
37645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Displaying the segment array.                             ---*/
37745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
37845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
37945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
380dbb3584f591710a15a437918c0fc27e300993566florianstatic const HChar* show_SegKind ( SegKind sk )
38145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
38245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (sk) {
38345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFree:  return "    ";
38445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkAnonC: return "anon";
38545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkAnonV: return "ANON";
38645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFileC: return "file";
38745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFileV: return "FILE";
3881340c35bebb175c6d158361596ee6171b4cfc2a2tom      case SkShmC:  return "shm ";
38945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkResvn: return "RSVN";
39045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default:      return "????";
39145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
39245f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
39345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
394dbb3584f591710a15a437918c0fc27e300993566florianstatic const HChar* show_ShrinkMode ( ShrinkMode sm )
39545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
39645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (sm) {
39745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SmLower: return "SmLower";
39845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SmUpper: return "SmUpper";
39945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SmFixed: return "SmFixed";
40045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default: return "Sm?????";
40145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
40245f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
40345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
404ddaef35bf689bb5192881aa6d455050e1423df7cnjnstatic void show_len_concisely ( /*OUT*/HChar* buf, Addr start, Addr end )
40545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
406dbb3584f591710a15a437918c0fc27e300993566florian   const HChar* fmt;
407ddaef35bf689bb5192881aa6d455050e1423df7cnjn   ULong len = ((ULong)end) - ((ULong)start) + 1;
40845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
409ddaef35bf689bb5192881aa6d455050e1423df7cnjn   if (len < 10*1000*1000ULL) {
41045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      fmt = "%7llu";
41145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
412ddaef35bf689bb5192881aa6d455050e1423df7cnjn   else if (len < 999999ULL * (1ULL<<20)) {
41345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      fmt = "%6llum";
414ddaef35bf689bb5192881aa6d455050e1423df7cnjn      len >>= 20;
41545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
416ddaef35bf689bb5192881aa6d455050e1423df7cnjn   else if (len < 999999ULL * (1ULL<<30)) {
41745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      fmt = "%6llug";
418ddaef35bf689bb5192881aa6d455050e1423df7cnjn      len >>= 30;
41945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
420ddaef35bf689bb5192881aa6d455050e1423df7cnjn   else if (len < 999999ULL * (1ULL<<40)) {
42145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      fmt = "%6llut";
422ddaef35bf689bb5192881aa6d455050e1423df7cnjn      len >>= 40;
42345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
42445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   else {
42545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      fmt = "%6llue";
426ddaef35bf689bb5192881aa6d455050e1423df7cnjn      len >>= 50;
42745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
428ddaef35bf689bb5192881aa6d455050e1423df7cnjn   ML_(am_sprintf)(buf, fmt, len);
42945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
43045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
43145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Show full details of an NSegment */
43245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
433a0d557c70142e7c518b4f3757f580645b57405bcflorianstatic void show_nsegment_full ( Int logLevel, Int segNo, const NSegment* seg )
43445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
435ddaef35bf689bb5192881aa6d455050e1423df7cnjn   HChar len_buf[20];
4364ecd48360351f666f008148c12a24cbda455c6b1florian   const HChar* name = ML_(am_get_segname)( seg->fnIdx );
437ddaef35bf689bb5192881aa6d455050e1423df7cnjn
438346ee2f7978bf2ab1ead4982e56870da276fc44bflorian   if (name == NULL)
439346ee2f7978bf2ab1ead4982e56870da276fc44bflorian      name = "(none)";
440616cf594d1c06d74632ef291c51c0545e3906f92sewardj
441ddaef35bf689bb5192881aa6d455050e1423df7cnjn   show_len_concisely(len_buf, seg->start, seg->end);
442ddaef35bf689bb5192881aa6d455050e1423df7cnjn
443ddaef35bf689bb5192881aa6d455050e1423df7cnjn   VG_(debugLog)(
444ddaef35bf689bb5192881aa6d455050e1423df7cnjn      logLevel, "aspacem",
445a5e06c36bf9d93461bc8c4351e960888020ea1c4florian      "%3d: %s %010lx-%010lx %s %c%c%c%c%c %s "
446a5e06c36bf9d93461bc8c4351e960888020ea1c4florian      "d=0x%03llx i=%-7llu o=%-7lld (%d,%d) %s\n",
447ddaef35bf689bb5192881aa6d455050e1423df7cnjn      segNo, show_SegKind(seg->kind),
448a5e06c36bf9d93461bc8c4351e960888020ea1c4florian      seg->start, seg->end, len_buf,
449ddaef35bf689bb5192881aa6d455050e1423df7cnjn      seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',
450ddaef35bf689bb5192881aa6d455050e1423df7cnjn      seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',
451ddaef35bf689bb5192881aa6d455050e1423df7cnjn      seg->isCH ? 'H' : '-',
45245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      show_ShrinkMode(seg->smode),
453e6c3b4348515ac6ea803b8c1908c476a05261f71philippe      seg->dev, seg->ino, seg->offset,
4544ecd48360351f666f008148c12a24cbda455c6b1florian      ML_(am_segname_get_seqnr)(seg->fnIdx), seg->fnIdx,
455bcf1d7f5230fae63eee2fad64258f3cc1dbd72fdflorian      name
45645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   );
45745f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
45845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
45945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
46045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Show an NSegment in a user-friendly-ish way. */
46145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
4623297124fa2116737066ac3cd709f18fdd5405163florianstatic void show_nsegment ( Int logLevel, Int segNo, const NSegment* seg )
46345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
46445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   HChar len_buf[20];
465ddaef35bf689bb5192881aa6d455050e1423df7cnjn   show_len_concisely(len_buf, seg->start, seg->end);
46645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
46745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (seg->kind) {
46845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
46945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFree:
47045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
47145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            logLevel, "aspacem",
472a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "%3d: %s %010lx-%010lx %s\n",
47345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            segNo, show_SegKind(seg->kind),
474a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            seg->start, seg->end, len_buf
47545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         );
47645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
47745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
4781340c35bebb175c6d158361596ee6171b4cfc2a2tom      case SkAnonC: case SkAnonV: case SkShmC:
47945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
48045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            logLevel, "aspacem",
481a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "%3d: %s %010lx-%010lx %s %c%c%c%c%c\n",
48245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            segNo, show_SegKind(seg->kind),
483a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            seg->start, seg->end, len_buf,
48445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',
48545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',
48645f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->isCH ? 'H' : '-'
48745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         );
48845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
48945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
49045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFileC: case SkFileV:
49145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
49245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            logLevel, "aspacem",
493a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "%3d: %s %010lx-%010lx %s %c%c%c%c%c d=0x%03llx "
494a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "i=%-7llu o=%-7lld (%d,%d)\n",
49545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            segNo, show_SegKind(seg->kind),
496a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            seg->start, seg->end, len_buf,
49745f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',
49845f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',
49945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->isCH ? 'H' : '-',
500e6c3b4348515ac6ea803b8c1908c476a05261f71philippe            seg->dev, seg->ino, seg->offset,
5014ecd48360351f666f008148c12a24cbda455c6b1florian            ML_(am_segname_get_seqnr)(seg->fnIdx), seg->fnIdx
50245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         );
50345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
50445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
50545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkResvn:
50645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
50745f4e7c91119c7d01a59f5e827c67841632c9314sewardj            logLevel, "aspacem",
508a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "%3d: %s %010lx-%010lx %s %c%c%c%c%c %s\n",
50945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            segNo, show_SegKind(seg->kind),
510a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            seg->start, seg->end, len_buf,
51145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',
51245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',
51345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            seg->isCH ? 'H' : '-',
51445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            show_ShrinkMode(seg->smode)
51545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         );
51645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
51745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
51845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default:
51945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
52045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            logLevel, "aspacem",
52145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            "%3d: ???? UNKNOWN SEGMENT KIND\n",
52245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            segNo
52345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         );
52445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
52545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
52645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
52745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
52845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Print out the segment array (debugging only!). */
529dbb3584f591710a15a437918c0fc27e300993566florianvoid VG_(am_show_nsegments) ( Int logLevel, const HChar* who )
53045f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
53145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int i;
53245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(logLevel, "aspacem",
533346ee2f7978bf2ab1ead4982e56870da276fc44bflorian                 "<<< SHOW_SEGMENTS: %s (%d segments)\n",
534346ee2f7978bf2ab1ead4982e56870da276fc44bflorian                 who, nsegments_used);
5354ecd48360351f666f008148c12a24cbda455c6b1florian   ML_(am_show_segnames)( logLevel, who);
53645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = 0; i < nsegments_used; i++)
53745f4e7c91119c7d01a59f5e827c67841632c9314sewardj     show_nsegment( logLevel, i, &nsegments[i] );
53845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(logLevel, "aspacem",
53945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                 ">>>\n");
54045f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
54145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
54245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
54345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Get the filename corresponding to this segment, if known and if it
54495af4ce809c85e3659843aa4156089c80b2b4353florian   has one. */
545d3166c4cf9d2545242da71d8baeaaf203b02a09dflorianconst HChar* VG_(am_get_filename)( NSegment const * seg )
54645f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
54745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(seg);
5484ecd48360351f666f008148c12a24cbda455c6b1florian   return ML_(am_get_segname)( seg->fnIdx );
54945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
55045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
551ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorian/* Collect up the start addresses of segments whose kind matches one of
552ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorian   the kinds specified in kind_mask.
55345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   The interface is a bit strange in order to avoid potential
55445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segment-creation races caused by dynamic allocation of the result
55545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   buffer *starts.
55645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
55745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   The function first computes how many entries in the result
55845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   buffer *starts will be needed.  If this number <= nStarts,
55945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   they are placed in starts[0..], and the number is returned.
56045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   If nStarts is not large enough, nothing is written to
56145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   starts[0..], and the negation of the size is returned.
56245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
56345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Correct use of this function may mean calling it multiple times in
56445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   order to establish a suitably-sized buffer. */
56545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
566ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorianInt VG_(am_get_segment_starts)( UInt kind_mask, Addr* starts, Int nStarts )
56745f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
56845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int i, j, nSegs;
56945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
57045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* don't pass dumbass arguments */
5717af930d9cbf43d775f205d61a5429658dd57266fflorian   aspacem_assert(nStarts > 0);
57245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
57345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nSegs = 0;
57445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = 0; i < nsegments_used; i++) {
575ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorian      if ((nsegments[i].kind & kind_mask) != 0)
576ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorian         nSegs++;
57745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
57845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
57945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nSegs > nStarts) {
58045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* The buffer isn't big enough.  Tell the caller how big it needs
58145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         to be. */
58245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return -nSegs;
58345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
58445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
58545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* There's enough space.  So write into the result buffer. */
58645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nSegs <= nStarts);
58745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
58845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   j = 0;
58945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = 0; i < nsegments_used; i++) {
590ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorian      if ((nsegments[i].kind & kind_mask) != 0)
591ea8a88c21eecdd9e91c75ccbd3c864e708e2f41bflorian         starts[j++] = nsegments[i].start;
59245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
59345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
59445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(j == nSegs); /* this should not fail */
59545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return nSegs;
59645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
59745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
59845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
59945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
60045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
60145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Sanity checking and preening of the segment array.        ---*/
60245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
60345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
60445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
60545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Check representational invariants for NSegments. */
60645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
6073297124fa2116737066ac3cd709f18fdd5405163florianstatic Bool sane_NSegment ( const NSegment* s )
60845f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
60945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (s == NULL) return False;
61045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
61145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* No zero sized segments and no wraparounds. */
612fb823ae9d34cd7dfe189990a9ccfb933762319a1florian   if (s->start > s->end) return False;
61345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
61445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* require page alignment */
61545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!VG_IS_PAGE_ALIGNED(s->start)) return False;
61645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!VG_IS_PAGE_ALIGNED(s->end+1)) return False;
61745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
61845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (s->kind) {
61945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
62045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFree:
62145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return
62245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s->smode == SmFixed
62345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1
62445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && !s->hasR && !s->hasW && !s->hasX && !s->hasT
62545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && !s->isCH;
62645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
6271340c35bebb175c6d158361596ee6171b4cfc2a2tom      case SkAnonC: case SkAnonV: case SkShmC:
62845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return
62945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s->smode == SmFixed
63045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1
63145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && (s->kind==SkAnonC ? True : !s->isCH);
63245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
63345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFileC: case SkFileV:
63445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return
63545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s->smode == SmFixed
6364ecd48360351f666f008148c12a24cbda455c6b1florian            && ML_(am_sane_segname)(s->fnIdx)
63745f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && !s->isCH;
63845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
63945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkResvn:
64045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return
64145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1
64245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && !s->hasR && !s->hasW && !s->hasX && !s->hasT
64345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            && !s->isCH;
64445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
64545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default:
64645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return False;
64745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
64845f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
64945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
65045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
65145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Try merging s2 into s1, if possible.  If successful, s1 is
65245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   modified, and True is returned.  Otherwise s1 is unchanged and
65345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   False is returned. */
65445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
6553297124fa2116737066ac3cd709f18fdd5405163florianstatic Bool maybe_merge_nsegments ( NSegment* s1, const NSegment* s2 )
65645f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
65745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (s1->kind != s2->kind)
65845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
65945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
66045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (s1->end+1 != s2->start)
66145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
66245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
66345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* reject cases which would cause wraparound */
66445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (s1->start > s2->end)
66545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
66645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
66745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (s1->kind) {
66845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
66945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFree:
67045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         s1->end = s2->end;
67145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return True;
67245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
67345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkAnonC: case SkAnonV:
67445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (s1->hasR == s2->hasR && s1->hasW == s2->hasW
67545f4e7c91119c7d01a59f5e827c67841632c9314sewardj             && s1->hasX == s2->hasX && s1->isCH == s2->isCH) {
67645f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s1->end = s2->end;
67745f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s1->hasT |= s2->hasT;
67845f4e7c91119c7d01a59f5e827c67841632c9314sewardj            return True;
67945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
68045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
68145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
68245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFileC: case SkFileV:
68345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (s1->hasR == s2->hasR
68445f4e7c91119c7d01a59f5e827c67841632c9314sewardj             && s1->hasW == s2->hasW && s1->hasX == s2->hasX
68545f4e7c91119c7d01a59f5e827c67841632c9314sewardj             && s1->dev == s2->dev && s1->ino == s2->ino
68645f4e7c91119c7d01a59f5e827c67841632c9314sewardj             && s2->offset == s1->offset
68745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                              + ((ULong)s2->start) - ((ULong)s1->start) ) {
68845f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s1->end = s2->end;
68945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            s1->hasT |= s2->hasT;
6904ecd48360351f666f008148c12a24cbda455c6b1florian            ML_(am_dec_refcount)(s1->fnIdx);
69145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            return True;
69245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
69345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
69445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
6951340c35bebb175c6d158361596ee6171b4cfc2a2tom      case SkShmC:
6961340c35bebb175c6d158361596ee6171b4cfc2a2tom         return False;
6971340c35bebb175c6d158361596ee6171b4cfc2a2tom
698613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      case SkResvn:
699613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj         if (s1->smode == SmFixed && s2->smode == SmFixed) {
700613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj            s1->end = s2->end;
701613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj            return True;
702613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj         }
703613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj
70445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default:
70545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
70645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
70745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
70845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
70945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return False;
71045f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
71145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
71245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
71345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Sanity-check and canonicalise the segment array (merge mergable
71445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segments).  Returns True if any segments were merged. */
71545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
71645f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Bool preen_nsegments ( void )
71745f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
71895af4ce809c85e3659843aa4156089c80b2b4353florian   Int i, r, w, nsegments_used_old = nsegments_used;
71945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
72045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Pass 1: check the segment array covers the entire address space
72145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      exactly once, and also that each segment is sane. */
72245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments_used > 0);
72345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[0].start == Addr_MIN);
72445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[nsegments_used-1].end == Addr_MAX);
72545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
72645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sane_NSegment(&nsegments[0]));
72745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = 1; i < nsegments_used; i++) {
72845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(sane_NSegment(&nsegments[i]));
72945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(nsegments[i-1].end+1 == nsegments[i].start);
73045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
73145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
73245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Pass 2: merge as much as possible, using
73345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      maybe_merge_segments. */
73445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   w = 0;
73545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (r = 1; r < nsegments_used; r++) {
73645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (maybe_merge_nsegments(&nsegments[w], &nsegments[r])) {
73745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* nothing */
73845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      } else {
73945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         w++;
74045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (w != r)
74145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            nsegments[w] = nsegments[r];
74245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
74345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
74445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   w++;
74545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(w > 0 && w <= nsegments_used);
74645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments_used = w;
74745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
74845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return nsegments_used != nsegments_used_old;
74945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
75045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
75145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
75245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Check the segment array corresponds with the kernel's view of
75345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   memory layout.  sync_check_ok returns True if no anomalies were
75445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   found, else False.  In the latter case the mismatching segments are
75545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   displayed.
75645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
75745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   The general idea is: we get the kernel to show us all its segments
75845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   and also the gaps in between.  For each such interval, try and find
75945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   a sequence of appropriate intervals in our segment array which
76045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   cover or more than cover the kernel's interval, and which all have
76145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   suitable kinds/permissions etc.
76245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
76345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Although any specific kernel interval is not matched exactly to a
76445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   valgrind interval or sequence thereof, eventually any disagreement
76545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   on mapping boundaries will be detected.  This is because, if for
76645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   example valgrind's intervals cover a greater range than the current
76745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   kernel interval, it must be the case that a neighbouring free-space
76845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   interval belonging to valgrind cannot cover the neighbouring
76945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   free-space interval belonging to the kernel.  So the disagreement
77045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   is detected.
77145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
77245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   In other words, we examine each kernel interval in turn, and check
77345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   we do not disagree over the range of that interval.  Because all of
77445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   the address space is examined, any disagreements must eventually be
77545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   detected.
77679048ce723a3463c70257ce647f04b111de71863sewardj*/
77745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
77845f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Bool sync_check_ok = False;
77945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
78045f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void sync_check_mapping_callback ( Addr addr, SizeT len, UInt prot,
781c4431bfe04c7490ea2d74939d222d87f13f30960njn                                          ULong dev, ULong ino, Off64T offset,
782dbb3584f591710a15a437918c0fc27e300993566florian                                          const HChar* filename )
78345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
784aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj   Int  iLo, iHi, i;
785954d6bb39f9109ee58b69d346894c50b78605c50florian   Bool sloppyXcheck, sloppyRcheck;
78645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
78745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* If a problem has already been detected, don't continue comparing
78845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      segments, so as to avoid flooding the output with error
78945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      messages. */
790f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if !defined(VGO_darwin)
791f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* GrP fixme not */
79245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!sync_check_ok)
79345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return;
794f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
79545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0)
79645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return;
79745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
79845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* The kernel should not give us wraparounds. */
79945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(addr <= addr + len - 1);
80045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
80145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iLo = find_nsegment_idx( addr );
80245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iHi = find_nsegment_idx( addr + len - 1 );
80345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
80445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* These 5 should be guaranteed by find_nsegment_idx. */
80545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(0 <= iLo && iLo < nsegments_used);
80645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(0 <= iHi && iHi < nsegments_used);
80745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(iLo <= iHi);
80845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[iLo].start <= addr );
80945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[iHi].end   >= addr + len - 1 );
81045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
811aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj   /* x86 doesn't differentiate 'x' and 'r' (at least, all except the
812c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      most recent NX-bit enabled CPUs) and so recent kernels attempt
813c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      to provide execute protection by placing all executable mappings
814c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      low down in the address space and then reducing the size of the
815c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      code segment to prevent code at higher addresses being executed.
816c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom
817c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      These kernels report which mappings are really executable in
818c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      the /proc/self/maps output rather than mirroring what was asked
819c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      for when each mapping was created. In order to cope with this we
820b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      have a sloppyXcheck mode which we enable on x86 and s390 - in this
821b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj      mode we allow the kernel to report execute permission when we weren't
822c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      expecting it but not vice versa. */
823b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj#  if defined(VGA_x86) || defined (VGA_s390x)
824c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom   sloppyXcheck = True;
8254c245e595b9f6300d3120408ca873f7115d9cc7dnjn#  else
8264c245e595b9f6300d3120408ca873f7115d9cc7dnjn   sloppyXcheck = False;
827aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj#  endif
828aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj
829954d6bb39f9109ee58b69d346894c50b78605c50florian   /* Some kernels on s390 provide 'r' permission even when it was not
830a6cece92d30ee2213e6fd1960488e6f19022855brhyskidd      explicitly requested. It seems that 'x' permission implies 'r'.
831a6cece92d30ee2213e6fd1960488e6f19022855brhyskidd      This behaviour also occurs on OS X. */
832a6cece92d30ee2213e6fd1960488e6f19022855brhyskidd#  if defined(VGA_s390x) || defined(VGO_darwin)
833954d6bb39f9109ee58b69d346894c50b78605c50florian   sloppyRcheck = True;
834954d6bb39f9109ee58b69d346894c50b78605c50florian#  else
835954d6bb39f9109ee58b69d346894c50b78605c50florian   sloppyRcheck = False;
836954d6bb39f9109ee58b69d346894c50b78605c50florian#  endif
837954d6bb39f9109ee58b69d346894c50b78605c50florian
83845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* NSegments iLo .. iHi inclusive should agree with the presented
83945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      data. */
84045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = iLo; i <= iHi; i++) {
84145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
84245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Bool same, cmp_offsets, cmp_devino;
843aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom      UInt seg_prot;
84445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
84545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* compare the kernel's offering against ours. */
84645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      same = nsegments[i].kind == SkAnonC
84745f4e7c91119c7d01a59f5e827c67841632c9314sewardj             || nsegments[i].kind == SkAnonV
84845f4e7c91119c7d01a59f5e827c67841632c9314sewardj             || nsegments[i].kind == SkFileC
8491340c35bebb175c6d158361596ee6171b4cfc2a2tom             || nsegments[i].kind == SkFileV
8501340c35bebb175c6d158361596ee6171b4cfc2a2tom             || nsegments[i].kind == SkShmC;
85145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
852aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom      seg_prot = 0;
853aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom      if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ;
854aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom      if (nsegments[i].hasW) seg_prot |= VKI_PROT_WRITE;
855aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom      if (nsegments[i].hasX) seg_prot |= VKI_PROT_EXEC;
856aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom
85745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      cmp_offsets
85845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         = nsegments[i].kind == SkFileC || nsegments[i].kind == SkFileV;
859616cf594d1c06d74632ef291c51c0545e3906f92sewardj
86045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      cmp_devino
86145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         = nsegments[i].dev != 0 || nsegments[i].ino != 0;
86245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
863616cf594d1c06d74632ef291c51c0545e3906f92sewardj      /* Consider other reasons to not compare dev/inode */
864f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_linux)
865616cf594d1c06d74632ef291c51c0545e3906f92sewardj      /* bproc does some godawful hack on /dev/zero at process
866616cf594d1c06d74632ef291c51c0545e3906f92sewardj         migration, which changes the name of it, and its dev & ino */
867616cf594d1c06d74632ef291c51c0545e3906f92sewardj      if (filename && 0==VG_(strcmp)(filename, "/dev/zero (deleted)"))
868616cf594d1c06d74632ef291c51c0545e3906f92sewardj         cmp_devino = False;
869616cf594d1c06d74632ef291c51c0545e3906f92sewardj
870f36e99ae1e4abc42b1b35bbdafc19a19e149b490sewardj      /* hack apparently needed on MontaVista Linux */
871f36e99ae1e4abc42b1b35bbdafc19a19e149b490sewardj      if (filename && VG_(strstr)(filename, "/.lib-ro/"))
872f36e99ae1e4abc42b1b35bbdafc19a19e149b490sewardj         cmp_devino = False;
873f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
874f36e99ae1e4abc42b1b35bbdafc19a19e149b490sewardj
875f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_darwin)
876f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // GrP fixme kernel info doesn't have dev/inode
877f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      cmp_devino = False;
878f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
879f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // GrP fixme V and kernel don't agree on offsets
880f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      cmp_offsets = False;
881f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
882f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
883c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      /* If we are doing sloppy execute permission checks then we
884c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom         allow segment to have X permission when we weren't expecting
885c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom         it (but not vice versa) so if the kernel reported execute
886c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom         permission then pretend that this segment has it regardless
887c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom         of what we were expecting. */
888c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom      if (sloppyXcheck && (prot & VKI_PROT_EXEC) != 0) {
889c28e3ddb9aaf5b6cc093c91eabb42e1e884444edtom         seg_prot |= VKI_PROT_EXEC;
890aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj      }
891aa34929c0d86ce6577bc43da5f3d922bc8d595a2sewardj
892954d6bb39f9109ee58b69d346894c50b78605c50florian      if (sloppyRcheck && (prot & (VKI_PROT_EXEC | VKI_PROT_READ)) ==
893954d6bb39f9109ee58b69d346894c50b78605c50florian          (VKI_PROT_EXEC | VKI_PROT_READ)) {
894954d6bb39f9109ee58b69d346894c50b78605c50florian         seg_prot |= VKI_PROT_READ;
895954d6bb39f9109ee58b69d346894c50b78605c50florian      }
896954d6bb39f9109ee58b69d346894c50b78605c50florian
89745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      same = same
898aa55dcae7b925e113f6fe3eda73cd940f0e4f209tom             && seg_prot == prot
89945f4e7c91119c7d01a59f5e827c67841632c9314sewardj             && (cmp_devino
90045f4e7c91119c7d01a59f5e827c67841632c9314sewardj                   ? (nsegments[i].dev == dev && nsegments[i].ino == ino)
90145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                   : True)
90245f4e7c91119c7d01a59f5e827c67841632c9314sewardj             && (cmp_offsets
90345f4e7c91119c7d01a59f5e827c67841632c9314sewardj                   ? nsegments[i].start-nsegments[i].offset == addr-offset
90445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                   : True);
90545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (!same) {
906ddaef35bf689bb5192881aa6d455050e1423df7cnjn         Addr start = addr;
907ddaef35bf689bb5192881aa6d455050e1423df7cnjn         Addr end = start + len - 1;
908ddaef35bf689bb5192881aa6d455050e1423df7cnjn         HChar len_buf[20];
909ddaef35bf689bb5192881aa6d455050e1423df7cnjn         show_len_concisely(len_buf, start, end);
910ddaef35bf689bb5192881aa6d455050e1423df7cnjn
91145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         sync_check_ok = False;
912ddaef35bf689bb5192881aa6d455050e1423df7cnjn
91345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
91445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            0,"aspacem",
915ddaef35bf689bb5192881aa6d455050e1423df7cnjn              "segment mismatch: V's seg 1st, kernel's 2nd:\n");
916ddaef35bf689bb5192881aa6d455050e1423df7cnjn         show_nsegment_full( 0, i, &nsegments[i] );
917ddaef35bf689bb5192881aa6d455050e1423df7cnjn         VG_(debugLog)(0,"aspacem",
918a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "...: .... %010lx-%010lx %s %c%c%c.. ....... "
919a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "d=0x%03llx i=%-7llu o=%-7lld (.) m=. %s\n",
920a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            start, end, len_buf,
921ddaef35bf689bb5192881aa6d455050e1423df7cnjn            prot & VKI_PROT_READ  ? 'r' : '-',
922ddaef35bf689bb5192881aa6d455050e1423df7cnjn            prot & VKI_PROT_WRITE ? 'w' : '-',
923ddaef35bf689bb5192881aa6d455050e1423df7cnjn            prot & VKI_PROT_EXEC  ? 'x' : '-',
924dbb3584f591710a15a437918c0fc27e300993566florian            dev, ino, offset, filename ? filename : "(none)" );
925ddaef35bf689bb5192881aa6d455050e1423df7cnjn
926ddaef35bf689bb5192881aa6d455050e1423df7cnjn         return;
92745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
92845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
92945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
93045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Looks harmless.  Keep going. */
93145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return;
93245f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
93345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
93445f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void sync_check_gap_callback ( Addr addr, SizeT len )
93545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
93645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int iLo, iHi, i;
93745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
93845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* If a problem has already been detected, don't continue comparing
93945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      segments, so as to avoid flooding the output with error
94045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      messages. */
941f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if !defined(VGO_darwin)
942f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* GrP fixme not */
94345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!sync_check_ok)
94445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return;
945f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
94645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0)
94745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return;
94845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
94945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* The kernel should not give us wraparounds. */
95045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(addr <= addr + len - 1);
95145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
95245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iLo = find_nsegment_idx( addr );
95345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iHi = find_nsegment_idx( addr + len - 1 );
95445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
95545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* These 5 should be guaranteed by find_nsegment_idx. */
95645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(0 <= iLo && iLo < nsegments_used);
95745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(0 <= iHi && iHi < nsegments_used);
95845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(iLo <= iHi);
95945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[iLo].start <= addr );
96045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[iHi].end   >= addr + len - 1 );
96145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
96245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* NSegments iLo .. iHi inclusive should agree with the presented
96345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      data. */
96445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = iLo; i <= iHi; i++) {
96545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
96645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Bool same;
96745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
96845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* compare the kernel's offering against ours. */
96945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      same = nsegments[i].kind == SkFree
97045f4e7c91119c7d01a59f5e827c67841632c9314sewardj             || nsegments[i].kind == SkResvn;
97145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
97245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (!same) {
973ddaef35bf689bb5192881aa6d455050e1423df7cnjn         Addr start = addr;
974ddaef35bf689bb5192881aa6d455050e1423df7cnjn         Addr end = start + len - 1;
975ddaef35bf689bb5192881aa6d455050e1423df7cnjn         HChar len_buf[20];
976ddaef35bf689bb5192881aa6d455050e1423df7cnjn         show_len_concisely(len_buf, start, end);
977ddaef35bf689bb5192881aa6d455050e1423df7cnjn
97845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         sync_check_ok = False;
979ddaef35bf689bb5192881aa6d455050e1423df7cnjn
98045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(debugLog)(
98145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            0,"aspacem",
982ddaef35bf689bb5192881aa6d455050e1423df7cnjn              "segment mismatch: V's gap 1st, kernel's 2nd:\n");
983ddaef35bf689bb5192881aa6d455050e1423df7cnjn         show_nsegment_full( 0, i, &nsegments[i] );
984ddaef35bf689bb5192881aa6d455050e1423df7cnjn         VG_(debugLog)(0,"aspacem",
985a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            "   : .... %010lx-%010lx %s\n",
986a5e06c36bf9d93461bc8c4351e960888020ea1c4florian            start, end, len_buf);
987ddaef35bf689bb5192881aa6d455050e1423df7cnjn         return;
98845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
98945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
99045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
99145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Looks harmless.  Keep going. */
99245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return;
99345f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
99445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
99545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
99645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Sanity check: check that Valgrind and the kernel agree on the
99745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   address space layout.  Prints offending segments and call point if
99845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   a discrepancy is detected, but does not abort the system.  Returned
99945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool is False if a discrepancy was found. */
100045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
100145f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_do_sync_check) ( const HChar* fn,
100245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                             const HChar* file, Int line )
100345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
100445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sync_check_ok = True;
100545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (0)
100645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(0,"aspacem", "do_sync_check %s:%d\n", file,line);
1007cb249ab3febb3757a0b0582be21952efacf415e5sewardj   parse_procselfmaps( sync_check_mapping_callback,
1008cb249ab3febb3757a0b0582be21952efacf415e5sewardj                       sync_check_gap_callback );
100945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!sync_check_ok) {
101045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(0,"aspacem",
101145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                      "sync check at %s:%d (%s): FAILED\n",
101245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                      file, line, fn);
101345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(0,"aspacem", "\n");
101445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
101545f4e7c91119c7d01a59f5e827c67841632c9314sewardj#     if 0
101645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      {
10177b7d59405204f88cb944155d6bc5114025ebda98florian         HChar buf[100];   // large enough
101845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(am_show_nsegments)(0,"post syncheck failure");
101945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(sprintf)(buf, "/bin/cat /proc/%d/maps", VG_(getpid)());
102045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(system)(buf);
102145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
102245f4e7c91119c7d01a59f5e827c67841632c9314sewardj#     endif
102345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
102445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
102545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sync_check_ok;
102645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
102745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1028297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj/* Hook to allow sanity checks to be done from aspacemgr-common.c. */
1029297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardjvoid ML_(am_do_sanity_check)( void )
1030297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj{
1031297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   AM_SANITY_CHECK;
1032297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj}
1033297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj
103445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
103545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
103645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
103745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Low level access / modification of the segment array.     ---*/
103845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
103945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
104045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
104145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Binary search the interval array for a given address.  Since the
1042a364d119b3847143d804e388d7a37c2c82be93bfsewardj   array covers the entire address space the search cannot fail.  The
1043a364d119b3847143d804e388d7a37c2c82be93bfsewardj   _WRK function does the real work.  Its caller (just below) caches
1044a364d119b3847143d804e388d7a37c2c82be93bfsewardj   the results thereof, to save time.  With N_CACHE of 63 we get a hit
1045a364d119b3847143d804e388d7a37c2c82be93bfsewardj   rate exceeding 90% when running OpenOffice.
1046a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1047a364d119b3847143d804e388d7a37c2c82be93bfsewardj   Re ">> 12", it doesn't matter that the page size of some targets
1048a364d119b3847143d804e388d7a37c2c82be93bfsewardj   might be different from 12.  Really "(a >> 12) % N_CACHE" is merely
1049a364d119b3847143d804e388d7a37c2c82be93bfsewardj   a hash function, and the actual cache entry is always validated
1050a364d119b3847143d804e388d7a37c2c82be93bfsewardj   correctly against the selected cache entry before use.
1051a364d119b3847143d804e388d7a37c2c82be93bfsewardj*/
1052a364d119b3847143d804e388d7a37c2c82be93bfsewardj/* Don't call find_nsegment_idx_WRK; use find_nsegment_idx instead. */
1053a364d119b3847143d804e388d7a37c2c82be93bfsewardj__attribute__((noinline))
1054a364d119b3847143d804e388d7a37c2c82be93bfsewardjstatic Int find_nsegment_idx_WRK ( Addr a )
1055548be6d64c58729588a559b1512ad7625bc1b86esewardj{
105645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr a_mid_lo, a_mid_hi;
105745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int  mid,
105845f4e7c91119c7d01a59f5e827c67841632c9314sewardj        lo = 0,
105945f4e7c91119c7d01a59f5e827c67841632c9314sewardj        hi = nsegments_used-1;
106045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   while (True) {
106145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* current unsearched space is from lo to hi, inclusive. */
106245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (lo > hi) {
106345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* Not found.  This can't happen. */
1064297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj         ML_(am_barf)("find_nsegment_idx: not found");
106545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
106645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      mid      = (lo + hi) / 2;
106745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      a_mid_lo = nsegments[mid].start;
106845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      a_mid_hi = nsegments[mid].end;
106945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
107045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (a < a_mid_lo) { hi = mid-1; continue; }
107145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (a > a_mid_hi) { lo = mid+1; continue; }
107245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(a >= a_mid_lo && a <= a_mid_hi);
107345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(0 <= mid && mid < nsegments_used);
107445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return mid;
107545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
107645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
107745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1078a364d119b3847143d804e388d7a37c2c82be93bfsewardjinline static Int find_nsegment_idx ( Addr a )
1079a364d119b3847143d804e388d7a37c2c82be93bfsewardj{
1080bbfcb260e026d9da39f5528677f23f619ed686cdsewardj#  define N_CACHE 131 /*prime*/
1081a364d119b3847143d804e388d7a37c2c82be93bfsewardj   static Addr cache_pageno[N_CACHE];
1082a364d119b3847143d804e388d7a37c2c82be93bfsewardj   static Int  cache_segidx[N_CACHE];
1083a364d119b3847143d804e388d7a37c2c82be93bfsewardj   static Bool cache_inited = False;
1084a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1085a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#  ifdef N_Q_M_STATS
1086a364d119b3847143d804e388d7a37c2c82be93bfsewardj   static UWord n_q = 0;
1087a364d119b3847143d804e388d7a37c2c82be93bfsewardj   static UWord n_m = 0;
1088a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   n_q++;
1089a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (0 == (n_q & 0xFFFF))
1090a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      VG_(debugLog)(0,"xxx","find_nsegment_idx: %lu %lu\n", n_q, n_m);
1091a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#  endif
1092a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1093a364d119b3847143d804e388d7a37c2c82be93bfsewardj   UWord ix;
1094a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1095a364d119b3847143d804e388d7a37c2c82be93bfsewardj   if (LIKELY(cache_inited)) {
1096a364d119b3847143d804e388d7a37c2c82be93bfsewardj      /* do nothing */
1097a364d119b3847143d804e388d7a37c2c82be93bfsewardj   } else {
1098a364d119b3847143d804e388d7a37c2c82be93bfsewardj      for (ix = 0; ix < N_CACHE; ix++) {
1099a364d119b3847143d804e388d7a37c2c82be93bfsewardj         cache_pageno[ix] = 0;
1100a364d119b3847143d804e388d7a37c2c82be93bfsewardj         cache_segidx[ix] = -1;
1101a364d119b3847143d804e388d7a37c2c82be93bfsewardj      }
1102a364d119b3847143d804e388d7a37c2c82be93bfsewardj      cache_inited = True;
1103a364d119b3847143d804e388d7a37c2c82be93bfsewardj   }
1104a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1105a364d119b3847143d804e388d7a37c2c82be93bfsewardj   ix = (a >> 12) % N_CACHE;
1106a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1107a364d119b3847143d804e388d7a37c2c82be93bfsewardj   if ((a >> 12) == cache_pageno[ix]
1108a364d119b3847143d804e388d7a37c2c82be93bfsewardj       && cache_segidx[ix] >= 0
1109a364d119b3847143d804e388d7a37c2c82be93bfsewardj       && cache_segidx[ix] < nsegments_used
1110a364d119b3847143d804e388d7a37c2c82be93bfsewardj       && nsegments[cache_segidx[ix]].start <= a
1111a364d119b3847143d804e388d7a37c2c82be93bfsewardj       && a <= nsegments[cache_segidx[ix]].end) {
1112a364d119b3847143d804e388d7a37c2c82be93bfsewardj      /* hit */
1113a364d119b3847143d804e388d7a37c2c82be93bfsewardj      /* aspacem_assert( cache_segidx[ix] == find_nsegment_idx_WRK(a) ); */
1114a364d119b3847143d804e388d7a37c2c82be93bfsewardj      return cache_segidx[ix];
1115a364d119b3847143d804e388d7a37c2c82be93bfsewardj   }
1116a364d119b3847143d804e388d7a37c2c82be93bfsewardj   /* miss */
1117a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#  ifdef N_Q_M_STATS
1118a364d119b3847143d804e388d7a37c2c82be93bfsewardj   n_m++;
1119a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes#  endif
1120a364d119b3847143d804e388d7a37c2c82be93bfsewardj   cache_segidx[ix] = find_nsegment_idx_WRK(a);
1121a364d119b3847143d804e388d7a37c2c82be93bfsewardj   cache_pageno[ix] = a >> 12;
1122a364d119b3847143d804e388d7a37c2c82be93bfsewardj   return cache_segidx[ix];
1123a364d119b3847143d804e388d7a37c2c82be93bfsewardj#  undef N_CACHE
1124a364d119b3847143d804e388d7a37c2c82be93bfsewardj}
1125a364d119b3847143d804e388d7a37c2c82be93bfsewardj
1126a364d119b3847143d804e388d7a37c2c82be93bfsewardj
11277cb1293f977ba78a06a63053e404493d545394edflorian/* Finds the segment containing 'a'.  Only returns non-SkFree segments. */
1128716f31ac50be6070a96b490d0b0bbd39b8e77342sewardjNSegment const * VG_(am_find_nsegment) ( Addr a )
112945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
113045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int i = find_nsegment_idx(a);
113145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(i >= 0 && i < nsegments_used);
113245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[i].start <= a);
113345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(a <= nsegments[i].end);
113445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nsegments[i].kind == SkFree)
113545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return NULL;
113645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   else
113745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return &nsegments[i];
113845f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
113945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
11408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Finds an anonymous segment containing 'a'. Returned pointer is read only. */
11418eb8bab992e3998c33770b0cdb16059a8b918a06sewardjNSegment const *VG_(am_find_anon_segment) ( Addr a )
11428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
11438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int i = find_nsegment_idx(a);
11448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(i >= 0 && i < nsegments_used);
11458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(nsegments[i].start <= a);
11468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(a <= nsegments[i].end);
11478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (nsegments[i].kind == SkAnonC || nsegments[i].kind == SkAnonV)
11488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      return &nsegments[i];
11498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   else
11508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      return NULL;
11518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
115245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1153686b8cad58180b009f8df91509d0a5da2191167aflorian/* Map segment pointer to segment index. */
11543e7986312a0ffc7646b0552d4c4ea3744a870e73florianstatic Int segAddr_to_index ( const NSegment* seg )
115545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
1156686b8cad58180b009f8df91509d0a5da2191167aflorian   aspacem_assert(seg >= &nsegments[0] && seg < &nsegments[nsegments_used]);
1157686b8cad58180b009f8df91509d0a5da2191167aflorian
1158686b8cad58180b009f8df91509d0a5da2191167aflorian   return seg - &nsegments[0];
115945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
116045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
116145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
11627cb1293f977ba78a06a63053e404493d545394edflorian/* Find the next segment along from 'here', if it is a non-SkFree segment. */
11633e7986312a0ffc7646b0552d4c4ea3744a870e73florianNSegment const * VG_(am_next_nsegment) ( const NSegment* here, Bool fwds )
116445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
116545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int i = segAddr_to_index(here);
1166686b8cad58180b009f8df91509d0a5da2191167aflorian
116745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (fwds) {
116845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      i++;
116945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (i >= nsegments_used)
117045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return NULL;
117145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else {
117245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      i--;
117345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (i < 0)
117445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return NULL;
117545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
11767cb1293f977ba78a06a63053e404493d545394edflorian   if (nsegments[i].kind == SkFree)
11777cb1293f977ba78a06a63053e404493d545394edflorian      return NULL;
11787cb1293f977ba78a06a63053e404493d545394edflorian   else
11797cb1293f977ba78a06a63053e404493d545394edflorian      return &nsegments[i];
118045f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
118145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
118245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
118345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Trivial fn: return the total amount of space in anonymous mappings,
118445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   both for V and the client.  Is used for printing stats in
118545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   out-of-memory messages. */
118645f4e7c91119c7d01a59f5e827c67841632c9314sewardjULong VG_(am_get_anonsize_total)( void )
118745f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
118845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int   i;
118945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   ULong total = 0;
119045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = 0; i < nsegments_used; i++) {
119145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (nsegments[i].kind == SkAnonC || nsegments[i].kind == SkAnonV) {
119245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         total += (ULong)nsegments[i].end
119345f4e7c91119c7d01a59f5e827c67841632c9314sewardj                  - (ULong)nsegments[i].start + 1ULL;
119445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
119545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
119645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return total;
119745f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
119845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
119945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1200adfff76735ea5bca870dec8f382b225728e1b32dphilippe/* Test if a piece of memory is addressable by client or by valgrind with at
120145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   least the "prot" protection permissions by examining the underlying
1202a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   segments. The KINDS argument specifies the allowed segments ADDR may
1203a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   belong to in order to be considered "valid".
120445f4e7c91119c7d01a59f5e827c67841632c9314sewardj*/
120545f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic
1206a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorianBool is_valid_for( UInt kinds, Addr start, SizeT len, UInt prot )
120745f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
120845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int  i, iLo, iHi;
120945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool needR, needW, needX;
121045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
121145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0)
121245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return True; /* somewhat dubious case */
121345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (start + len < start)
121445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False; /* reject wraparounds */
121545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
121645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needR = toBool(prot & VKI_PROT_READ);
121745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needW = toBool(prot & VKI_PROT_WRITE);
121845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needX = toBool(prot & VKI_PROT_EXEC);
121945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
122045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iLo = find_nsegment_idx(start);
122145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(start >= nsegments[iLo].start);
122245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
122345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (start+len-1 <= nsegments[iLo].end) {
122445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* This is a speedup hack which avoids calling find_nsegment_idx
122545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         a second time when possible.  It is always correct to just
122645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         use the "else" clause below, but is_valid_for_client is
122745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         called a lot by the leak checker, so avoiding pointless calls
122845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         to find_nsegment_idx, which can be expensive, is helpful. */
122945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      iHi = iLo;
123045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else {
123145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      iHi = find_nsegment_idx(start + len - 1);
123245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
123345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1234a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   for (i = iLo; i <= iHi; i++) {
1235a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian      if ( (nsegments[i].kind & kinds) != 0
1236a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian           && (needR ? nsegments[i].hasR : True)
1237a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian           && (needW ? nsegments[i].hasW : True)
1238a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian           && (needX ? nsegments[i].hasX : True) ) {
1239a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian         /* ok */
1240a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian      } else {
1241a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian         return False;
124245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
124345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
1244a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian
124545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return True;
124645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
124745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
124845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Test if a piece of memory is addressable by the client with at
124945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   least the "prot" protection permissions by examining the underlying
125045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segments. */
125145f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_is_valid_for_client)( Addr start, SizeT len,
125245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                  UInt prot )
125345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
1254a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   const UInt kinds = SkFileC | SkAnonC | SkShmC;
1255a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian
1256a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   return is_valid_for(kinds, start, len, prot);
125745f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
125845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
125945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Variant of VG_(am_is_valid_for_client) which allows free areas to
126045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   be consider part of the client's addressable space.  It also
126145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   considers reservations to be allowable, since from the client's
126245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   point of view they don't exist. */
126345f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_is_valid_for_client_or_free_or_resvn)
126445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   ( Addr start, SizeT len, UInt prot )
126545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
1266a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   const UInt kinds = SkFileC | SkAnonC | SkShmC | SkFree | SkResvn;
1267a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian
1268a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   return is_valid_for(kinds, start, len, prot);
126945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
127045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1271e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr/* Checks if a piece of memory consists of either free or reservation
1272e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr   segments. */
1273e8b9ee37f8a49881dffd1900b5c397768f54a53biraisrBool VG_(am_is_free_or_resvn)( Addr start, SizeT len )
1274e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr{
1275e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr   const UInt kinds = SkFree | SkResvn;
1276e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr
1277e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr   return is_valid_for(kinds, start, len, 0);
1278e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr}
1279e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr
128045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1281adfff76735ea5bca870dec8f382b225728e1b32dphilippeBool VG_(am_is_valid_for_valgrind) ( Addr start, SizeT len, UInt prot )
128245f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
1283a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   const UInt kinds = SkFileV | SkAnonV;
1284a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian
1285a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian   return is_valid_for(kinds, start, len, prot);
128645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
128745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
128845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
128945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Returns True if any part of the address range is marked as having
129045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   translations made from it.  This is used to determine when to
129145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   discard code, so if in doubt return True. */
129245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
129345f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Bool any_Ts_in_range ( Addr start, SizeT len )
129445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
129545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int iLo, iHi, i;
129645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(len > 0);
129745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(start + len > start);
129845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iLo = find_nsegment_idx(start);
129945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iHi = find_nsegment_idx(start + len - 1);
130045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = iLo; i <= iHi; i++) {
130145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (nsegments[i].hasT)
130245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return True;
130345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
130445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return False;
130545f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
130645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
130745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
13088f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian/* Check whether ADDR looks like an address or address-to-be located in an
13098f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian   extensible client stack segment. Return true if
13108f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian   (1) ADDR is located in an already mapped stack segment, OR
13118f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian   (2) ADDR is located in a reservation segment into which an abutting SkAnonC
1312017d8f5410cff379575eee4f5056fb1a82a6526bflorian       segment can be extended. */
13138f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florianBool VG_(am_addr_is_in_extensible_client_stack)( Addr addr )
1314017d8f5410cff379575eee4f5056fb1a82a6526bflorian{
1315017d8f5410cff379575eee4f5056fb1a82a6526bflorian   const NSegment *seg = nsegments + find_nsegment_idx(addr);
1316017d8f5410cff379575eee4f5056fb1a82a6526bflorian
1317017d8f5410cff379575eee4f5056fb1a82a6526bflorian   switch (seg->kind) {
1318017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkFree:
1319017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkAnonV:
1320017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkFileV:
1321017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkFileC:
1322017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkShmC:
13238f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian      return False;
1324017d8f5410cff379575eee4f5056fb1a82a6526bflorian
1325017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkResvn: {
13268f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian      if (seg->smode != SmUpper) return False;
1327ad4e979f408239dabbaae955d8ffcb84a51a5c85florian      /* If the abutting segment towards higher addresses is an SkAnonC
1328017d8f5410cff379575eee4f5056fb1a82a6526bflorian         segment, then ADDR is a future stack pointer. */
1329017d8f5410cff379575eee4f5056fb1a82a6526bflorian      const NSegment *next = VG_(am_next_nsegment)(seg, /*forward*/ True);
13308f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian      if (next == NULL || next->kind != SkAnonC) return False;
1331017d8f5410cff379575eee4f5056fb1a82a6526bflorian
1332017d8f5410cff379575eee4f5056fb1a82a6526bflorian      /* OK; looks like a stack segment */
13338f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian      return True;
1334017d8f5410cff379575eee4f5056fb1a82a6526bflorian   }
1335017d8f5410cff379575eee4f5056fb1a82a6526bflorian
1336017d8f5410cff379575eee4f5056fb1a82a6526bflorian   case SkAnonC: {
1337017d8f5410cff379575eee4f5056fb1a82a6526bflorian      /* If the abutting segment towards lower addresses is an SkResvn
1338017d8f5410cff379575eee4f5056fb1a82a6526bflorian         segment, then ADDR is a stack pointer into mapped memory. */
1339017d8f5410cff379575eee4f5056fb1a82a6526bflorian      const NSegment *next = VG_(am_next_nsegment)(seg, /*forward*/ False);
1340d57686f198efb6fea6b0f5dd932bdf4f2299a96aflorian      if (next == NULL || next->kind != SkResvn || next->smode != SmUpper)
13418f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian         return False;
1342017d8f5410cff379575eee4f5056fb1a82a6526bflorian
1343017d8f5410cff379575eee4f5056fb1a82a6526bflorian      /* OK; looks like a stack segment */
13448f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian      return True;
1345017d8f5410cff379575eee4f5056fb1a82a6526bflorian   }
1346017d8f5410cff379575eee4f5056fb1a82a6526bflorian
1347017d8f5410cff379575eee4f5056fb1a82a6526bflorian   default:
1348017d8f5410cff379575eee4f5056fb1a82a6526bflorian      aspacem_assert(0);   // should never happen
1349017d8f5410cff379575eee4f5056fb1a82a6526bflorian   }
1350017d8f5410cff379575eee4f5056fb1a82a6526bflorian}
1351017d8f5410cff379575eee4f5056fb1a82a6526bflorian
135245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
135345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
135445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Modifying the segment array, and constructing segments.   ---*/
135545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
135645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
135745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
135845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Split the segment containing 'a' into two, so that 'a' is
135945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   guaranteed to be the start of a new segment.  If 'a' is already the
136045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   start of a segment, do nothing. */
136145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
136245f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void split_nsegment_at ( Addr a )
136345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
136445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int i, j;
136545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
136645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(a > 0);
136745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(a));
136845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
136945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   i = find_nsegment_idx(a);
137045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(i >= 0 && i < nsegments_used);
137145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
137245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nsegments[i].start == a)
137345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* 'a' is already the start point of a segment, so nothing to be
137445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         done. */
137545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return;
137645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
137745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* else we have to slide the segments upwards to make a hole */
137845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nsegments_used >= VG_N_SEGMENTS)
1379297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj      ML_(am_barf_toolow)("VG_N_SEGMENTS");
138045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (j = nsegments_used-1; j > i; j--)
138145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      nsegments[j+1] = nsegments[j];
138245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments_used++;
138345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
138445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments[i+1]       = nsegments[i];
138545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments[i+1].start = a;
138645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments[i].end     = a-1;
138745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
138845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nsegments[i].kind == SkFileV || nsegments[i].kind == SkFileC)
138945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      nsegments[i+1].offset
139045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         += ((ULong)nsegments[i+1].start) - ((ULong)nsegments[i].start);
139145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
13924ecd48360351f666f008148c12a24cbda455c6b1florian   ML_(am_inc_refcount)(nsegments[i].fnIdx);
1393346ee2f7978bf2ab1ead4982e56870da276fc44bflorian
139445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sane_NSegment(&nsegments[i]));
139545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sane_NSegment(&nsegments[i+1]));
139645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
139745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
139845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
139945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Do the minimum amount of segment splitting necessary to ensure that
140045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sLo is the first address denoted by some segment and sHi is the
140145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   highest address denoted by some other segment.  Returns the indices
140245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   of the lowest and highest segments in the range. */
140345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
140445f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic
140545f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid split_nsegments_lo_and_hi ( Addr sLo, Addr sHi,
140645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 /*OUT*/Int* iLo,
140745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 /*OUT*/Int* iHi )
140845f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
140945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sLo < sHi);
141045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(sLo));
141145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(sHi+1));
141245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
141345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (sLo > 0)
141445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      split_nsegment_at(sLo);
141545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (sHi < sHi+1)
141645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      split_nsegment_at(sHi+1);
141745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
141845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   *iLo = find_nsegment_idx(sLo);
141945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   *iHi = find_nsegment_idx(sHi);
142045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(0 <= *iLo && *iLo < nsegments_used);
142145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(0 <= *iHi && *iHi < nsegments_used);
142245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(*iLo <= *iHi);
142345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[*iLo].start == sLo);
142445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[*iHi].end == sHi);
142545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Not that I'm overly paranoid or anything, definitely not :-) */
142645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
142745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
142845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
142945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Add SEG to the collection, deleting/truncating any it overlaps.
143045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   This deals with all the tricky cases of splitting up segments as
143145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needed. */
143245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
14333297124fa2116737066ac3cd709f18fdd5405163florianstatic void add_segment ( const NSegment* seg )
143445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
143545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int  i, iLo, iHi, delta;
143645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool segment_is_sane;
143745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
143845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr sStart = seg->start;
143945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr sEnd   = seg->end;
144045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
144145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sStart <= sEnd);
144245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(sStart));
144345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(sEnd+1));
144445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
144545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segment_is_sane = sane_NSegment(seg);
1446ddaef35bf689bb5192881aa6d455050e1423df7cnjn   if (!segment_is_sane) show_nsegment_full(0,-1,seg);
144745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(segment_is_sane);
144845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
144945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   split_nsegments_lo_and_hi( sStart, sEnd, &iLo, &iHi );
145045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1451a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   /* Increase the reference count of SEG's name. We need to do this
1452a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      *before* decreasing the reference count of the names of the replaced
1453a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      segments. Consider the case where the segment name of SEG and one of
1454a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      the replaced segments are the same. If the refcount of that name is 1,
1455a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      then decrementing first would put the slot for that name on the free
1456a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      list. Attempting to increment the refcount later would then fail
1457a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      because the slot is no longer allocated. */
1458a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   ML_(am_inc_refcount)(seg->fnIdx);
1459a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
146045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Now iLo .. iHi inclusive is the range of segment indices which
146145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      seg will replace.  If we're replacing more than one segment,
1462346ee2f7978bf2ab1ead4982e56870da276fc44bflorian      slide those above the range down to fill the hole. Before doing
1463346ee2f7978bf2ab1ead4982e56870da276fc44bflorian      that decrement the reference counters for the segments names of
1464346ee2f7978bf2ab1ead4982e56870da276fc44bflorian      the replaced segments. */
1465346ee2f7978bf2ab1ead4982e56870da276fc44bflorian   for (i = iLo; i <= iHi; ++i)
14664ecd48360351f666f008148c12a24cbda455c6b1florian      ML_(am_dec_refcount)(nsegments[i].fnIdx);
146745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   delta = iHi - iLo;
146845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(delta >= 0);
146945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (delta > 0) {
147045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      for (i = iLo; i < nsegments_used-delta; i++)
147145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         nsegments[i] = nsegments[i+delta];
147245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      nsegments_used -= delta;
147345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
147445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
147545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments[iLo] = *seg;
147645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
147745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   (void)preen_nsegments();
147845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (0) VG_(am_show_nsegments)(0,"AFTER preen (add_segment)");
147945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
148045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
148145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
148245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Clear out an NSegment record. */
148345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
148445f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void init_nsegment ( /*OUT*/NSegment* seg )
148545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
148645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->kind     = SkFree;
148745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->start    = 0;
148845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->end      = 0;
148945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->smode    = SmFixed;
149045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->dev      = 0;
149145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->ino      = 0;
1492f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom   seg->mode     = 0;
149345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->offset   = 0;
149445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->fnIdx    = -1;
149545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->hasR = seg->hasW = seg->hasX = seg->hasT = seg->isCH = False;
149645f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
149745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
149845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Make an NSegment which holds a reservation. */
149945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
150045f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void init_resvn ( /*OUT*/NSegment* seg, Addr start, Addr end )
150145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
150245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(start < end);
150345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start));
150445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(end+1));
150545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment(seg);
150645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->kind  = SkResvn;
150745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->start = start;
150845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg->end   = end;
150945f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
151045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
151145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
151245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
151345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
151445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Startup, including reading /proc/self/maps.               ---*/
151545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
151645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
151745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
151845f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void read_maps_callback ( Addr addr, SizeT len, UInt prot,
1519c4431bfe04c7490ea2d74939d222d87f13f30960njn                                 ULong dev, ULong ino, Off64T offset,
1520dbb3584f591710a15a437918c0fc27e300993566florian                                 const HChar* filename )
152145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
152245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment seg;
152345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
152445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start  = addr;
152545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end    = addr+len-1;
152645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.dev    = dev;
152745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.ino    = ino;
152845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.offset = offset;
152945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR   = toBool(prot & VKI_PROT_READ);
153045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW   = toBool(prot & VKI_PROT_WRITE);
153145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX   = toBool(prot & VKI_PROT_EXEC);
153245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasT   = False;
153345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1534981ffbd4d8f303856a0183e801b934ed7e3cd957florian   /* A segment in the initial /proc/self/maps is considered a FileV
1535981ffbd4d8f303856a0183e801b934ed7e3cd957florian      segment if either it has a file name associated with it or both its
1536981ffbd4d8f303856a0183e801b934ed7e3cd957florian      device and inode numbers are != 0. See bug #124528. */
153745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind = SkAnonV;
1538981ffbd4d8f303856a0183e801b934ed7e3cd957florian   if (filename || (dev != 0 && ino != 0))
1539c2fe246d0d85a81c1f63ad3e6f7496667e2f6711sewardj      seg.kind = SkFileV;
154038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
154138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  if defined(VGO_darwin)
1542f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // GrP fixme no dev/ino on darwin
1543f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (offset != 0)
154438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      seg.kind = SkFileV;
154538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  endif // defined(VGO_darwin)
154638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
154738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  if defined(VGP_arm_linux)
154838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   /* The standard handling of entries read from /proc/self/maps will
154938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      cause the faked up commpage segment to have type SkAnonV, which
155038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      is a problem because it contains code we want the client to
155138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      execute, and so later m_translate will segfault the client when
155238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      it tries to go in there.  Hence change the ownership of it here
155338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      to the client (SkAnonC).  The least-worst kludge I could think
155438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      of. */
155538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   if (addr == ARM_LINUX_FAKE_COMMPAGE_START
155638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj       && addr + len == ARM_LINUX_FAKE_COMMPAGE_END1
155738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj       && seg.kind == SkAnonV)
155838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      seg.kind = SkAnonC;
155938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  endif // defined(VGP_arm_linux)
156038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
1561c2fe246d0d85a81c1f63ad3e6f7496667e2f6711sewardj   if (filename)
15624ecd48360351f666f008148c12a24cbda455c6b1florian      seg.fnIdx = ML_(am_allocate_segname)( filename );
156345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
156445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (0) show_nsegment( 2,0, &seg );
156545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
1566548be6d64c58729588a559b1512ad7625bc1b86esewardj}
1567548be6d64c58729588a559b1512ad7625bc1b86esewardj
156882e7a5439ce882f99cdb49bc064616d95124738dflorianBool
156982e7a5439ce882f99cdb49bc064616d95124738dflorianVG_(am_is_valid_for_aspacem_minAddr)( Addr addr, const HChar **errmsg )
157082e7a5439ce882f99cdb49bc064616d95124738dflorian{
1571d738b46bd7dd65fe55736744fb3be1f0159d3a58florian   const Addr min = VKI_PAGE_SIZE;
157282e7a5439ce882f99cdb49bc064616d95124738dflorian#if VG_WORDSIZE == 4
157382e7a5439ce882f99cdb49bc064616d95124738dflorian   const Addr max = 0x40000000;  // 1Gb
157482e7a5439ce882f99cdb49bc064616d95124738dflorian#else
157582e7a5439ce882f99cdb49bc064616d95124738dflorian   const Addr max = 0x200000000; // 8Gb
157682e7a5439ce882f99cdb49bc064616d95124738dflorian#endif
157782e7a5439ce882f99cdb49bc064616d95124738dflorian   Bool ok = VG_IS_PAGE_ALIGNED(addr) && addr >= min && addr <= max;
157882e7a5439ce882f99cdb49bc064616d95124738dflorian
157982e7a5439ce882f99cdb49bc064616d95124738dflorian   if (errmsg) {
158082e7a5439ce882f99cdb49bc064616d95124738dflorian      *errmsg = "";
158182e7a5439ce882f99cdb49bc064616d95124738dflorian      if (! ok) {
158282e7a5439ce882f99cdb49bc064616d95124738dflorian         const HChar fmt[] = "Must be a page aligned address between "
158382e7a5439ce882f99cdb49bc064616d95124738dflorian                             "0x%lx and 0x%lx";
158482e7a5439ce882f99cdb49bc064616d95124738dflorian         static HChar buf[sizeof fmt + 2 * 16];   // large enough
158582e7a5439ce882f99cdb49bc064616d95124738dflorian         ML_(am_sprintf)(buf, fmt, min, max);
158682e7a5439ce882f99cdb49bc064616d95124738dflorian         *errmsg = buf;
158782e7a5439ce882f99cdb49bc064616d95124738dflorian      }
158882e7a5439ce882f99cdb49bc064616d95124738dflorian   }
158982e7a5439ce882f99cdb49bc064616d95124738dflorian   return ok;
159082e7a5439ce882f99cdb49bc064616d95124738dflorian}
159182e7a5439ce882f99cdb49bc064616d95124738dflorian
159238a74d2cc4670e3eb559adff51a376cd6ec98005philippe/* See description in pub_core_aspacemgr.h */
159345f4e7c91119c7d01a59f5e827c67841632c9314sewardjAddr VG_(am_startup) ( Addr sp_at_startup )
159445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
159545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment seg;
159638a74d2cc4670e3eb559adff51a376cd6ec98005philippe   Addr     suggested_clstack_end;
159745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
159845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sizeof(Word)   == sizeof(void*));
159945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sizeof(Addr)   == sizeof(void*));
160045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sizeof(SizeT)  == sizeof(void*));
160145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(sizeof(SSizeT) == sizeof(void*));
160245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1603346ee2f7978bf2ab1ead4982e56870da276fc44bflorian   /* Initialise the string table for segment names. */
16044ecd48360351f666f008148c12a24cbda455c6b1florian   ML_(am_segnames_init)();
1605346ee2f7978bf2ab1ead4982e56870da276fc44bflorian
1606419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   /* Check that we can store the largest imaginable dev, ino and
1607419060073e7943846cc9e0bcdcb25258d90da2dcsewardj      offset numbers in an NSegment. */
1608419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   aspacem_assert(sizeof(seg.dev)    == 8);
1609419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   aspacem_assert(sizeof(seg.ino)    == 8);
1610419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   aspacem_assert(sizeof(seg.offset) == 8);
1611419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   aspacem_assert(sizeof(seg.mode)   == 4);
161245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
161345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Add a single interval covering the entire address space. */
161445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment(&seg);
161545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind        = SkFree;
161645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start       = Addr_MIN;
161745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end         = Addr_MAX;
161845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments[0]    = seg;
161945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nsegments_used  = 1;
162045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1621e4d78123089e55bec64a4f848bdc09556192e259philippe   aspacem_minAddr = VG_(clo_aspacem_minAddr);
1622e4d78123089e55bec64a4f848bdc09556192e259philippe
1623ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   // --- Darwin -------------------------------------------
1624f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_darwin)
1625f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1626f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# if VG_WORDSIZE == 4
1627f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_maxAddr = (Addr) 0xffffffff;
1628f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1629f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_cStart = aspacem_minAddr;
1630f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_vStart = 0xf0000000;  // 0xc0000000..0xf0000000 available
1631f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# else
1632f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_maxAddr = (Addr) 0x7fffffffffff;
1633f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1634f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_cStart = aspacem_minAddr;
1635f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_vStart = 0x700000000000; // 0x7000:00000000..0x7fff:5c000000 avail
1636f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // 0x7fff:5c000000..0x7fff:ffe00000? is stack, dyld, shared cache
1637f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# endif
1638f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
163938a74d2cc4670e3eb559adff51a376cd6ec98005philippe   suggested_clstack_end = -1; // ignored; Mach-O specifies its stack
1640f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
1641ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   // --- Solaris ------------------------------------------
16428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(VGO_solaris)
16438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  if VG_WORDSIZE == 4
16448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /*
16458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      Intended address space partitioning:
16468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
16478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ,--------------------------------, 0x00000000
16488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      | initial stack given to V by OS |
16518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------| 0x08000000
16528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |          client text           |
16538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |          client stack          |
1658ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      |--------------------------------| 0x58000000
16598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |            V's text            |
16608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |     dynamic shared objects     |
16658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      '--------------------------------' 0xffffffff
16668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
16678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      */
16688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
16698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Anonymous pages need to fit under user limit (USERLIMIT32)
16708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      which is 4KB + 16MB below the top of the 32-bit range. */
16718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    ifdef ENABLE_INNER
16728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     aspacem_maxAddr = (Addr)0x4fffffff; // 1.25GB
16738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     aspacem_vStart  = (Addr)0x40000000; // 1GB
16748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    else
16758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     aspacem_maxAddr = (Addr)0xfefff000 - 1; // 4GB - 16MB - 4KB
16768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     aspacem_vStart  = (Addr)0x50000000; // 1.25GB
16778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    endif
16788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  elif VG_WORDSIZE == 8
16798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /*
16808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      Intended address space partitioning:
16818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
16828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ,--------------------------------, 0x00000000_00000000
16838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------| 0x00000000_00400000
16858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |          client text           |
16868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |          client stack          |
1691ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      |--------------------------------| 0x00000000_58000000
16928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |            V's text            |
16938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
16968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |     dynamic shared objects     |
1697ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      |--------------------------------| 0x0000001f_ffffffff
16988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
16998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |                                |
17008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      |--------------------------------|
17018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      | initial stack given to V by OS |
17028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      '--------------------------------' 0xffffffff_ffffffff
17038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
17048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      */
17058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
17068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Kernel likes to place objects at the end of the address space.
1707ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      However accessing memory beyond 128GB makes memcheck slow
17088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      (see memcheck/mc_main.c, internal representation). Therefore:
17098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      - mmapobj() syscall is emulated so that libraries are subject to
17108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj        Valgrind's aspacemgr control
17118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      - Kernel shared pages (such as schedctl and hrt) are left as they are
17128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj        because kernel cannot be told where they should be put */
17138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    ifdef ENABLE_INNER
17148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     aspacem_maxAddr = (Addr) 0x0000000fffffffff; // 64GB
17158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     aspacem_vStart  = (Addr) 0x0000000800000000; // 32GB
1716ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes#    else
1717ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     aspacem_maxAddr = (Addr) 0x0000001fffffffff; // 128GB
1718ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     aspacem_vStart  = (Addr) 0x0000001000000000; // 64GB
17198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    endif
17208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  else
17218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#    error "Unknown word size"
17228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
17238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
17248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_cStart = aspacem_minAddr;
17258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  ifdef ENABLE_INNER
17268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   suggested_clstack_end = (Addr) 0x37ff0000 - 1; // 64kB below V's text
1727ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes#  else
1728ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   suggested_clstack_end = (Addr) 0x57ff0000 - 1; // 64kB below V's text
17298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  endif
17308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
1731ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   // --- Linux --------------------------------------------
17328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
1733f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
173445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Establish address limits and block out unusable parts
173545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      accordingly. */
173645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
173745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem",
1738a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    "        sp_at_startup = 0x%010lx (supplied)\n",
1739a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    sp_at_startup );
174045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
174145f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  if VG_WORDSIZE == 8
1742ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes     aspacem_maxAddr = (Addr)0x2000000000ULL - 1; // 128G
174370c91dd9e5768adb7195fe7280aac359c7848984sewardj#    ifdef ENABLE_INNER
1744420c6555d36e7ad19cf3b9e068397435d4acca51sewardj     { Addr cse = VG_PGROUNDDN( sp_at_startup ) - 1;
1745420c6555d36e7ad19cf3b9e068397435d4acca51sewardj       if (aspacem_maxAddr > cse)
1746420c6555d36e7ad19cf3b9e068397435d4acca51sewardj          aspacem_maxAddr = cse;
1747420c6555d36e7ad19cf3b9e068397435d4acca51sewardj     }
174870c91dd9e5768adb7195fe7280aac359c7848984sewardj#    endif
174945f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  else
175070c91dd9e5768adb7195fe7280aac359c7848984sewardj     aspacem_maxAddr = VG_PGROUNDDN( sp_at_startup ) - 1;
175145f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  endif
175245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1753e4d78123089e55bec64a4f848bdc09556192e259philippe   aspacem_cStart = aspacem_minAddr;
1754d4f5aac98c40fb66d193587d72d024e86cdf3075philippe   aspacem_vStart = VG_PGROUNDUP(aspacem_minAddr
1755d4f5aac98c40fb66d193587d72d024e86cdf3075philippe                                 + (aspacem_maxAddr - aspacem_minAddr + 1) / 2);
175645f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  ifdef ENABLE_INNER
1757ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   aspacem_vStart -= 0x20000000; // 512M
175845f4e7c91119c7d01a59f5e827c67841632c9314sewardj#  endif
175945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
176038a74d2cc4670e3eb559adff51a376cd6ec98005philippe   suggested_clstack_end = aspacem_maxAddr - 16*1024*1024ULL
176145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                           + VKI_PAGE_SIZE;
176245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
17638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif
1764ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   // --- (end) --------------------------------------------
1765f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
176645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_minAddr));
176745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_maxAddr + 1));
176845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_cStart));
176945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_vStart));
177038a74d2cc4670e3eb559adff51a376cd6ec98005philippe   aspacem_assert(VG_IS_PAGE_ALIGNED(suggested_clstack_end + 1));
177145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
177245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem",
1773a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    "              minAddr = 0x%010lx (computed)\n",
1774a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    aspacem_minAddr);
177545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem",
1776a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    "              maxAddr = 0x%010lx (computed)\n",
1777a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    aspacem_maxAddr);
177845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem",
1779a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    "               cStart = 0x%010lx (computed)\n",
1780a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    aspacem_cStart);
178145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem",
1782a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    "               vStart = 0x%010lx (computed)\n",
1783a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    aspacem_vStart);
178445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem",
1785a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    "suggested_clstack_end = 0x%010lx (computed)\n",
1786a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    suggested_clstack_end);
178745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
178845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (aspacem_cStart > Addr_MIN) {
178945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      init_resvn(&seg, Addr_MIN, aspacem_cStart-1);
179045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      add_segment(&seg);
179145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
179245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (aspacem_maxAddr < Addr_MAX) {
179345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      init_resvn(&seg, aspacem_maxAddr+1, Addr_MAX);
179445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      add_segment(&seg);
179545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
179645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
179745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Create a 1-page reservation at the notional initial
179845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      client/valgrind boundary.  This isn't strictly necessary, but
179945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      because the advisor does first-fit and starts searches for
180045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      valgrind allocations at the boundary, this is kind of necessary
180145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      in order to get it to start allocating in the right place. */
180245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_resvn(&seg, aspacem_vStart,  aspacem_vStart + VKI_PAGE_SIZE - 1);
180345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment(&seg);
180445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
180545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(am_show_nsegments)(2, "Initial layout");
180645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
180745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "aspacem", "Reading /proc/self/maps\n");
1808cb249ab3febb3757a0b0582be21952efacf415e5sewardj   parse_procselfmaps( read_maps_callback, NULL );
180938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   /* NB: on arm-linux, parse_procselfmaps automagically kludges up
181038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      (iow, hands to its callbacks) a description of the ARM Commpage,
181138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      since that's not listed in /proc/self/maps (kernel bug IMO).  We
181238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      have to fake up its existence in parse_procselfmaps and not
181338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      merely add it here as an extra segment, because doing the latter
181438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      causes sync checking to fail: we see we have an extra segment in
181538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      the segments array, which isn't listed in /proc/self/maps.
181638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      Hence we must make it appear that /proc/self/maps contained this
181738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      segment all along.  Sigh. */
181845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
181945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(am_show_nsegments)(2, "With contents of /proc/self/maps");
182045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
182145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
182238a74d2cc4670e3eb559adff51a376cd6ec98005philippe   return suggested_clstack_end;
182345f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
182445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
182545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
182645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
182745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
182845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- The core query-notify mechanism.                          ---*/
182945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
183045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
183145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
183245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Query aspacem to ask where a mapping should go. */
183345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
18343297124fa2116737066ac3cd709f18fdd5405163florianAddr VG_(am_get_advisory) ( const MapRequest*  req,
18353297124fa2116737066ac3cd709f18fdd5405163florian                            Bool  forClient,
183645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                            /*OUT*/Bool* ok )
183745f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
183845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* This function implements allocation policy.
183945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
184045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      The nature of the allocation request is determined by req, which
184145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      specifies the start and length of the request and indicates
184245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      whether the start address is mandatory, a hint, or irrelevant,
184345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      and by forClient, which says whether this is for the client or
184445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      for V.
184545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
184645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Return values: the request can be vetoed (*ok is set to False),
184745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      in which case the caller should not attempt to proceed with
184845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      making the mapping.  Otherwise, *ok is set to True, the caller
184945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      may proceed, and the preferred address at which the mapping
185045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      should happen is returned.
185145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
185245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Note that this is an advisory system only: the kernel can in
185345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      fact do whatever it likes as far as placement goes, and we have
185445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      no absolute control over it.
185545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
185645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Allocations will never be granted in a reserved area.
185745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
185845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      The Default Policy is:
185945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
186045f4e7c91119c7d01a59f5e827c67841632c9314sewardj        Search the address space for two free intervals: one of them
186145f4e7c91119c7d01a59f5e827c67841632c9314sewardj        big enough to contain the request without regard to the
186245f4e7c91119c7d01a59f5e827c67841632c9314sewardj        specified address (viz, as if it was a floating request) and
186345f4e7c91119c7d01a59f5e827c67841632c9314sewardj        the other being able to contain the request at the specified
186445f4e7c91119c7d01a59f5e827c67841632c9314sewardj        address (viz, as if were a fixed request).  Then, depending on
186545f4e7c91119c7d01a59f5e827c67841632c9314sewardj        the outcome of the search and the kind of request made, decide
186645f4e7c91119c7d01a59f5e827c67841632c9314sewardj        whether the request is allowable and what address to advise.
186745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1868ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      The Default Policy is overridden by Policy Exception #1:
186945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
187045f4e7c91119c7d01a59f5e827c67841632c9314sewardj        If the request is for a fixed client map, we are prepared to
187145f4e7c91119c7d01a59f5e827c67841632c9314sewardj        grant it providing all areas inside the request are either
187245f4e7c91119c7d01a59f5e827c67841632c9314sewardj        free, reservations, or mappings belonging to the client.  In
187345f4e7c91119c7d01a59f5e827c67841632c9314sewardj        other words we are prepared to let the client trash its own
187445f4e7c91119c7d01a59f5e827c67841632c9314sewardj        mappings if it wants to.
187545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1876ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes      The Default Policy is overridden by Policy Exception #2:
187745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1878caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj        If the request is for a hinted client map, we are prepared to
1879caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj        grant it providing all areas inside the request are either
1880caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj        free or reservations.  In other words we are prepared to let
1881caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj        the client have a hinted mapping anywhere it likes provided
1882caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj        it does not trash either any of its own mappings or any of
1883caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj        valgrind's mappings.
188445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   */
188545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int  i, j;
188645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr holeStart, holeEnd, holeLen;
188745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool fixed_not_required;
188845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
18898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris)
18908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr startPoint = forClient ? aspacem_vStart - 1 : aspacem_maxAddr - 1;
18918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
189245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr startPoint = forClient ? aspacem_cStart : aspacem_vStart;
18938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif /* VGO_solaris */
189445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
18958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr reqStart = req->rkind==MFixed || req->rkind==MHint ? req->start : 0;
189645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr reqEnd   = reqStart + req->len - 1;
189745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr reqLen   = req->len;
189845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
189945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* These hold indices for segments found during search, or -1 if not
190045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      found. */
190145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int floatIdx = -1;
190245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int fixedIdx = -1;
190345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
190445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments_used > 0);
190545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
190645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (0) {
190745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(am_show_nsegments)(0,"getAdvisory");
1908a5e06c36bf9d93461bc8c4351e960888020ea1c4florian      VG_(debugLog)(0,"aspacem", "getAdvisory 0x%lx %lu\n",
1909a5e06c36bf9d93461bc8c4351e960888020ea1c4florian                    req->start, req->len);
191045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
191145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
191245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Reject zero-length requests */
191345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (req->len == 0) {
191445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      *ok = False;
191545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return 0;
191645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
191745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
191845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Reject wraparounds */
1919e354a1fd9e4a4ca836d3c6bbf159b5811fa25124florian   if (req->start + req->len < req->start) {
192045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      *ok = False;
192145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return 0;
192245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
192379048ce723a3463c70257ce647f04b111de71863sewardj
192445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* ------ Implement Policy Exception #1 ------ */
192545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1926caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj   if (forClient && req->rkind == MFixed) {
192745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Int  iLo   = find_nsegment_idx(reqStart);
192845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Int  iHi   = find_nsegment_idx(reqEnd);
192945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      Bool allow = True;
193045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      for (i = iLo; i <= iHi; i++) {
193145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (nsegments[i].kind == SkFree
193245f4e7c91119c7d01a59f5e827c67841632c9314sewardj             || nsegments[i].kind == SkFileC
193345f4e7c91119c7d01a59f5e827c67841632c9314sewardj             || nsegments[i].kind == SkAnonC
19341340c35bebb175c6d158361596ee6171b4cfc2a2tom             || nsegments[i].kind == SkShmC
193545f4e7c91119c7d01a59f5e827c67841632c9314sewardj             || nsegments[i].kind == SkResvn) {
193645f4e7c91119c7d01a59f5e827c67841632c9314sewardj            /* ok */
193745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         } else {
193845f4e7c91119c7d01a59f5e827c67841632c9314sewardj            allow = False;
193945f4e7c91119c7d01a59f5e827c67841632c9314sewardj            break;
194045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
194145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
194245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (allow) {
194345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* Acceptable.  Granted. */
194445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         *ok = True;
194545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return reqStart;
194645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
1947caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      /* Not acceptable.  Fail. */
1948caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      *ok = False;
1949caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      return 0;
1950caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj   }
1951caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj
1952caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj   /* ------ Implement Policy Exception #2 ------ */
1953caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj
1954caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj   if (forClient && req->rkind == MHint) {
1955caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      Int  iLo   = find_nsegment_idx(reqStart);
1956caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      Int  iHi   = find_nsegment_idx(reqEnd);
1957caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      Bool allow = True;
1958caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      for (i = iLo; i <= iHi; i++) {
1959caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj         if (nsegments[i].kind == SkFree
1960caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj             || nsegments[i].kind == SkResvn) {
1961caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj            /* ok */
1962caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj         } else {
1963caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj            allow = False;
1964caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj            break;
1965caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj         }
1966caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      }
1967caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      if (allow) {
1968caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj         /* Acceptable.  Granted. */
1969caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj         *ok = True;
1970caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj         return reqStart;
197145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
1972caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj      /* Not acceptable.  Fall through to the default policy. */
1973548be6d64c58729588a559b1512ad7625bc1b86esewardj   }
1974548be6d64c58729588a559b1512ad7625bc1b86esewardj
197545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* ------ Implement the Default Policy ------ */
1976548be6d64c58729588a559b1512ad7625bc1b86esewardj
197745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Don't waste time looking for a fixed match if not requested to. */
19788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   fixed_not_required = req->rkind == MAny || req->rkind == MAlign;
197945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
198045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   i = find_nsegment_idx(startPoint);
198145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
19828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris)
19838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define UPDATE_INDEX(index)                               \
19848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      (index)--;                                            \
19858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if ((index) <= 0)                                     \
19868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         (index) = nsegments_used - 1;
19878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define ADVISE_ADDRESS(segment)                           \
19888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj       VG_PGROUNDDN((segment)->end + 1 - reqLen)
19898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define ADVISE_ADDRESS_ALIGNED(segment)                   \
19908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj        VG_ROUNDDN((segment)->end + 1 - reqLen, req->start)
19918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
19928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else
19938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
19948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define UPDATE_INDEX(index)                               \
19958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      (index)++;                                            \
19968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if ((index) >= nsegments_used)                        \
19978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         (index) = 0;
19988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define ADVISE_ADDRESS(segment)                           \
19998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      (segment)->start
20008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#  define ADVISE_ADDRESS_ALIGNED(segment)                   \
20018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      VG_ROUNDUP((segment)->start, req->start)
20028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif /* VGO_solaris */
20038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
200445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Examine holes from index i back round to i-1.  Record the
200545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      index first fixed hole and the first floating hole which would
200645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      satisfy the request. */
200745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (j = 0; j < nsegments_used; j++) {
200845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
200945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (nsegments[i].kind != SkFree) {
20108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         UPDATE_INDEX(i);
201179048ce723a3463c70257ce647f04b111de71863sewardj         continue;
201245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
2013548be6d64c58729588a559b1512ad7625bc1b86esewardj
201445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      holeStart = nsegments[i].start;
201545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      holeEnd   = nsegments[i].end;
2016548be6d64c58729588a559b1512ad7625bc1b86esewardj
201745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Stay sane .. */
201845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(holeStart <= holeEnd);
201945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(aspacem_minAddr <= holeStart);
202045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(holeEnd <= aspacem_maxAddr);
2021548be6d64c58729588a559b1512ad7625bc1b86esewardj
20228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (req->rkind == MAlign) {
20238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         holeStart = VG_ROUNDUP(holeStart, req->start);
20248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         if (holeStart >= holeEnd) {
20258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            /* This hole can't be used. */
20268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            UPDATE_INDEX(i);
20278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            continue;
20288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         }
20298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
20308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
203145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* See if it's any use to us. */
203245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      holeLen = holeEnd - holeStart + 1;
2033548be6d64c58729588a559b1512ad7625bc1b86esewardj
203445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (fixedIdx == -1 && holeStart <= reqStart && reqEnd <= holeEnd)
203545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         fixedIdx = i;
203645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
203745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (floatIdx == -1 && holeLen >= reqLen)
203845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         floatIdx = i;
203945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
204045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Don't waste time searching once we've found what we wanted. */
204145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if ((fixed_not_required || fixedIdx >= 0) && floatIdx >= 0)
204245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
204345f4e7c91119c7d01a59f5e827c67841632c9314sewardj
20448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      UPDATE_INDEX(i);
204579048ce723a3463c70257ce647f04b111de71863sewardj   }
2046548be6d64c58729588a559b1512ad7625bc1b86esewardj
204745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(fixedIdx >= -1 && fixedIdx < nsegments_used);
204845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (fixedIdx >= 0)
204945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(nsegments[fixedIdx].kind == SkFree);
205079048ce723a3463c70257ce647f04b111de71863sewardj
205145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(floatIdx >= -1 && floatIdx < nsegments_used);
205245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (floatIdx >= 0)
205345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(nsegments[floatIdx].kind == SkFree);
205445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
205545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
205645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
205745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Now see if we found anything which can satisfy the request. */
205845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (req->rkind) {
205945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case MFixed:
206045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (fixedIdx >= 0) {
206145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            *ok = True;
206245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            return req->start;
206345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         } else {
206445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            *ok = False;
206545f4e7c91119c7d01a59f5e827c67841632c9314sewardj            return 0;
206645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
206745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
206845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case MHint:
206945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (fixedIdx >= 0) {
207045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            *ok = True;
207145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            return req->start;
207245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
207345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (floatIdx >= 0) {
207445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            *ok = True;
20758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            return ADVISE_ADDRESS(&nsegments[floatIdx]);
207645f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
207745f4e7c91119c7d01a59f5e827c67841632c9314sewardj         *ok = False;
207845f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return 0;
207945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case MAny:
208045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         if (floatIdx >= 0) {
208145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            *ok = True;
20828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            return ADVISE_ADDRESS(&nsegments[floatIdx]);
20838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         }
20848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         *ok = False;
20858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         return 0;
20868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      case MAlign:
20878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         if (floatIdx >= 0) {
20888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            *ok = True;
20898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            return ADVISE_ADDRESS_ALIGNED(&nsegments[floatIdx]);
209045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         }
209145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         *ok = False;
209245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         return 0;
209345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default:
209445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         break;
2095f6ec8ec39b3977f5a8ce446353ea990ae2c6e4b2njn   }
209645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
209745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /*NOTREACHED*/
2098297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   ML_(am_barf)("getAdvisory: unknown request kind");
209945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   *ok = False;
210045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return 0;
21018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
21028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef UPDATE_INDEX
21038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef ADVISE_ADDRESS
21048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef ADVISE_ADDRESS_ALIGNED
2105548be6d64c58729588a559b1512ad7625bc1b86esewardj}
2106548be6d64c58729588a559b1512ad7625bc1b86esewardj
210745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Convenience wrapper for VG_(am_get_advisory) for client floating or
210845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   fixed requests.  If start is zero, a floating request is issued; if
210945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   nonzero, a fixed request at that address is issued.  Same comments
211045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   about return values apply. */
2111548be6d64c58729588a559b1512ad7625bc1b86esewardj
211245f4e7c91119c7d01a59f5e827c67841632c9314sewardjAddr VG_(am_get_advisory_client_simple) ( Addr start, SizeT len,
211345f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                          /*OUT*/Bool* ok )
2114548be6d64c58729588a559b1512ad7625bc1b86esewardj{
211545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   MapRequest mreq;
211645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   mreq.rkind = start==0 ? MAny : MFixed;
211745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   mreq.start = start;
211845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   mreq.len   = len;
2119515e26933c61eed21ba8d74ecdfc89c217832fedphilippe   return VG_(am_get_advisory)( &mreq, True/*forClient*/, ok );
2120548be6d64c58729588a559b1512ad7625bc1b86esewardj}
2121548be6d64c58729588a559b1512ad7625bc1b86esewardj
212215e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe/* Similar to VG_(am_find_nsegment) but only returns free segments. */
212315e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippestatic NSegment const * VG_(am_find_free_nsegment) ( Addr a )
212415e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe{
212515e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   Int i = find_nsegment_idx(a);
212615e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   aspacem_assert(i >= 0 && i < nsegments_used);
212715e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   aspacem_assert(nsegments[i].start <= a);
212815e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   aspacem_assert(a <= nsegments[i].end);
212915e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   if (nsegments[i].kind == SkFree)
213015e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe      return &nsegments[i];
213115e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   else
213215e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe      return NULL;
213315e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe}
213415e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe
213515e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippeBool VG_(am_covered_by_single_free_segment)
213615e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   ( Addr start, SizeT len)
213715e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe{
213815e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   NSegment const* segLo = VG_(am_find_free_nsegment)( start );
213915e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   NSegment const* segHi = VG_(am_find_free_nsegment)( start + len - 1 );
214015e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe
214115e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe   return segLo != NULL && segHi != NULL && segLo == segHi;
214215e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe}
214315e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe
214479048ce723a3463c70257ce647f04b111de71863sewardj
214545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Notifies aspacem that the client completed an mmap successfully.
214645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   The segment array is updated accordingly.  If the returned Bool is
214745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   True, the caller should immediately discard translations from the
214845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   specified address range. */
214979048ce723a3463c70257ce647f04b111de71863sewardj
215045f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool
215145f4e7c91119c7d01a59f5e827c67841632c9314sewardjVG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags,
2152274461dcb67f680196c97e8afb7028a79b97dcb7sewardj                            Int fd, Off64T offset )
2153548be6d64c58729588a559b1512ad7625bc1b86esewardj{
215445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   HChar    buf[VKI_PATH_MAX];
2155419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   ULong    dev, ino;
2156f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom   UInt     mode;
215745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment seg;
215845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool     needDiscard;
215945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
216045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(len > 0);
216145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(a));
216245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(len));
2163274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(offset));
216445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
216545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Discard is needed if any of the just-trashed range had T. */
216645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needDiscard = any_Ts_in_range( a, len );
216745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
216845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
216945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind   = (flags & VKI_MAP_ANONYMOUS) ? SkAnonC : SkFileC;
217045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start  = a;
217145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end    = a + len - 1;
217245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR   = toBool(prot & VKI_PROT_READ);
217345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW   = toBool(prot & VKI_PROT_WRITE);
217445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX   = toBool(prot & VKI_PROT_EXEC);
217545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!(flags & VKI_MAP_ANONYMOUS)) {
21764395ad459576d155df4270a96bc46279c43d498anjn      // Nb: We ignore offset requests in anonymous mmaps (see bug #126722)
2177dadff0a77b92b9c81648850d628ab781b44965f9tom      seg.offset = offset;
2178dad944add53e6361751c6832066c00c456854622njn      if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
217945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         seg.dev = dev;
218045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         seg.ino = ino;
2181f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom         seg.mode = mode;
218245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
2183dad944add53e6361751c6832066c00c456854622njn      if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
21844ecd48360351f666f008148c12a24cbda455c6b1florian         seg.fnIdx = ML_(am_allocate_segname)( buf );
218545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
218679048ce723a3463c70257ce647f04b111de71863sewardj   }
218745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
218845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
218945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return needDiscard;
2190548be6d64c58729588a559b1512ad7625bc1b86esewardj}
2191548be6d64c58729588a559b1512ad7625bc1b86esewardj
21921340c35bebb175c6d158361596ee6171b4cfc2a2tom/* Notifies aspacem that the client completed a shmat successfully.
21931340c35bebb175c6d158361596ee6171b4cfc2a2tom   The segment array is updated accordingly.  If the returned Bool is
21941340c35bebb175c6d158361596ee6171b4cfc2a2tom   True, the caller should immediately discard translations from the
21951340c35bebb175c6d158361596ee6171b4cfc2a2tom   specified address range. */
21961340c35bebb175c6d158361596ee6171b4cfc2a2tom
21971340c35bebb175c6d158361596ee6171b4cfc2a2tomBool
21981340c35bebb175c6d158361596ee6171b4cfc2a2tomVG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot )
21991340c35bebb175c6d158361596ee6171b4cfc2a2tom{
22001340c35bebb175c6d158361596ee6171b4cfc2a2tom   NSegment seg;
22011340c35bebb175c6d158361596ee6171b4cfc2a2tom   Bool     needDiscard;
22021340c35bebb175c6d158361596ee6171b4cfc2a2tom
22031340c35bebb175c6d158361596ee6171b4cfc2a2tom   aspacem_assert(len > 0);
22041340c35bebb175c6d158361596ee6171b4cfc2a2tom   aspacem_assert(VG_IS_PAGE_ALIGNED(a));
22051340c35bebb175c6d158361596ee6171b4cfc2a2tom   aspacem_assert(VG_IS_PAGE_ALIGNED(len));
22061340c35bebb175c6d158361596ee6171b4cfc2a2tom
22071340c35bebb175c6d158361596ee6171b4cfc2a2tom   /* Discard is needed if any of the just-trashed range had T. */
22081340c35bebb175c6d158361596ee6171b4cfc2a2tom   needDiscard = any_Ts_in_range( a, len );
22091340c35bebb175c6d158361596ee6171b4cfc2a2tom
22101340c35bebb175c6d158361596ee6171b4cfc2a2tom   init_nsegment( &seg );
22111340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.kind   = SkShmC;
22121340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.start  = a;
22131340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.end    = a + len - 1;
22141340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.offset = 0;
22151340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.hasR   = toBool(prot & VKI_PROT_READ);
22161340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.hasW   = toBool(prot & VKI_PROT_WRITE);
22171340c35bebb175c6d158361596ee6171b4cfc2a2tom   seg.hasX   = toBool(prot & VKI_PROT_EXEC);
22181340c35bebb175c6d158361596ee6171b4cfc2a2tom   add_segment( &seg );
22191340c35bebb175c6d158361596ee6171b4cfc2a2tom   AM_SANITY_CHECK;
22201340c35bebb175c6d158361596ee6171b4cfc2a2tom   return needDiscard;
22211340c35bebb175c6d158361596ee6171b4cfc2a2tom}
22221340c35bebb175c6d158361596ee6171b4cfc2a2tom
222345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Notifies aspacem that an mprotect was completed successfully.  The
222445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segment array is updated accordingly.  Note, as with
222545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(am_notify_munmap), it is not the job of this function to reject
222645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   stupid mprotects, for example the client doing mprotect of
222745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   non-client areas.  Such requests should be intercepted earlier, by
222845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   the syscall wrapper for mprotect.  This function merely records
222945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   whatever it is told.  If the returned Bool is True, the caller
223045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   should immediately discard translations from the specified address
223145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   range. */
223245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
223345f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot )
223445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
223545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int  i, iLo, iHi;
223645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool newR, newW, newX, needDiscard;
223779048ce723a3463c70257ce647f04b111de71863sewardj
223845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start));
223945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(len));
2240548be6d64c58729588a559b1512ad7625bc1b86esewardj
224145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0)
224245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
2243548be6d64c58729588a559b1512ad7625bc1b86esewardj
224445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   newR = toBool(prot & VKI_PROT_READ);
224545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   newW = toBool(prot & VKI_PROT_WRITE);
224645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   newX = toBool(prot & VKI_PROT_EXEC);
224745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
224845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Discard is needed if we're dumping X permission */
224945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needDiscard = any_Ts_in_range( start, len ) && !newX;
225045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
225145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi );
225245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
225345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iLo = find_nsegment_idx(start);
225445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iHi = find_nsegment_idx(start + len - 1);
225545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
225645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   for (i = iLo; i <= iHi; i++) {
225745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Apply the permissions to all relevant segments. */
225845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      switch (nsegments[i].kind) {
22591340c35bebb175c6d158361596ee6171b4cfc2a2tom         case SkAnonC: case SkAnonV: case SkFileC: case SkFileV: case SkShmC:
226045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            nsegments[i].hasR = newR;
226145f4e7c91119c7d01a59f5e827c67841632c9314sewardj            nsegments[i].hasW = newW;
226245f4e7c91119c7d01a59f5e827c67841632c9314sewardj            nsegments[i].hasX = newX;
226345f4e7c91119c7d01a59f5e827c67841632c9314sewardj            aspacem_assert(sane_NSegment(&nsegments[i]));
226445f4e7c91119c7d01a59f5e827c67841632c9314sewardj            break;
226545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         default:
226645f4e7c91119c7d01a59f5e827c67841632c9314sewardj            break;
226745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
226845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
2269548be6d64c58729588a559b1512ad7625bc1b86esewardj
227045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Changing permissions could have made previously un-mergable
227145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      segments mergeable.  Therefore have to re-preen them. */
227245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   (void)preen_nsegments();
227345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
227445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return needDiscard;
2275548be6d64c58729588a559b1512ad7625bc1b86esewardj}
2276548be6d64c58729588a559b1512ad7625bc1b86esewardj
227779048ce723a3463c70257ce647f04b111de71863sewardj
227845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Notifies aspacem that an munmap completed successfully.  The
227945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segment array is updated accordingly.  As with
2280135c9f1d417cb4b1f453b8e6786ad55b89c9143eflorian   VG_(am_notify_mprotect), we merely record the given info, and don't
228145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   check it for sensibleness.  If the returned Bool is True, the
228245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   caller should immediately discard translations from the specified
228345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   address range. */
228445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
228545f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_notify_munmap)( Addr start, SizeT len )
228679048ce723a3463c70257ce647f04b111de71863sewardj{
228745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment seg;
228845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool     needDiscard;
228945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start));
229045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(len));
229179048ce723a3463c70257ce647f04b111de71863sewardj
229245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0)
229379048ce723a3463c70257ce647f04b111de71863sewardj      return False;
229479048ce723a3463c70257ce647f04b111de71863sewardj
229545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   needDiscard = any_Ts_in_range( start, len );
229679048ce723a3463c70257ce647f04b111de71863sewardj
229745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
229845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start = start;
229945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end   = start + len - 1;
2300613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj
2301613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj   /* The segment becomes unused (free).  Segments from above
2302613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      aspacem_maxAddr were originally SkResvn and so we make them so
2303613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      again.  Note, this isn't really right when the segment straddles
2304613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      the aspacem_maxAddr boundary - then really it should be split in
2305613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      two, the lower part marked as SkFree and the upper part as
2306613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      SkResvn.  Ah well. */
2307613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj   if (start > aspacem_maxAddr
2308613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj       && /* check previous comparison is meaningful */
2309613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj          aspacem_maxAddr < Addr_MAX)
2310613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      seg.kind = SkResvn;
23117cc2040098cb14f021e04ac44f127195b98a1c30sewardj   else
23127cc2040098cb14f021e04ac44f127195b98a1c30sewardj   /* Ditto for segments from below aspacem_minAddr. */
23137cc2040098cb14f021e04ac44f127195b98a1c30sewardj   if (seg.end < aspacem_minAddr && aspacem_minAddr > 0)
23147cc2040098cb14f021e04ac44f127195b98a1c30sewardj      seg.kind = SkResvn;
2315613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj   else
2316613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      seg.kind = SkFree;
2317613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj
231845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
231979048ce723a3463c70257ce647f04b111de71863sewardj
232045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Unmapping could create two adjacent free segments, so a preen is
232145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      needed.  add_segment() will do that, so no need to here. */
232245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
232345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return needDiscard;
232479048ce723a3463c70257ce647f04b111de71863sewardj}
232579048ce723a3463c70257ce647f04b111de71863sewardj
232679048ce723a3463c70257ce647f04b111de71863sewardj
232745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
232845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
232945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Handling mappings which do not arise directly from the    ---*/
233045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- simulation of the client.                                 ---*/
233145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
233245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
233379048ce723a3463c70257ce647f04b111de71863sewardj
233445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- --- map, unmap, protect  --- --- --- */
233579048ce723a3463c70257ce647f04b111de71863sewardj
233645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map a file at a fixed address for the client, and update the
233745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segment array accordingly. */
233879048ce723a3463c70257ce647f04b111de71863sewardj
233945f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_file_fixed_client)
2340274461dcb67f680196c97e8afb7028a79b97dcb7sewardj     ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset )
234145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
23428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   UInt flags = VKI_MAP_FIXED | VKI_MAP_PRIVATE;
23438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return VG_(am_mmap_named_file_fixed_client_flags)(start, length, prot, flags,
23448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                                     fd, offset, NULL);
23458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
23468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
23478eb8bab992e3998c33770b0cdb16059a8b918a06sewardjSysRes VG_(am_mmap_file_fixed_client_flags)
23488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset )
23498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
23508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return VG_(am_mmap_named_file_fixed_client_flags)(start, length, prot, flags,
23518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                                     fd, offset, NULL);
2352f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
2353f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
2354f76d27a697a7b0bf3b84490baf60623fc96a23afnjnSysRes VG_(am_mmap_named_file_fixed_client)
2355f76d27a697a7b0bf3b84490baf60623fc96a23afnjn     ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset, const HChar *name )
2356f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
23578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   UInt flags = VKI_MAP_FIXED | VKI_MAP_PRIVATE;
23588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return VG_(am_mmap_named_file_fixed_client_flags)(start, length, prot, flags,
23598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                                     fd, offset, name);
23608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
23618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
23628eb8bab992e3998c33770b0cdb16059a8b918a06sewardjSysRes VG_(am_mmap_named_file_fixed_client_flags)
23638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj     ( Addr start, SizeT length, UInt prot, UInt flags,
23648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj       Int fd, Off64T offset, const HChar *name )
23658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
236645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes     sres;
236745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment   seg;
236845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr       advised;
236945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool       ok;
237045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   MapRequest req;
2371419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   ULong      dev, ino;
2372f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom   UInt       mode;
237345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   HChar      buf[VKI_PATH_MAX];
237445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
237545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Not allowable. */
2376274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   if (length == 0
2377274461dcb67f680196c97e8afb7028a79b97dcb7sewardj       || !VG_IS_PAGE_ALIGNED(start)
2378274461dcb67f680196c97e8afb7028a79b97dcb7sewardj       || !VG_IS_PAGE_ALIGNED(offset))
237945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
238045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
238145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ask for an advisory.  If it's negative, fail immediately. */
238245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.rkind = MFixed;
238345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.start = start;
238445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.len   = length;
2385515e26933c61eed21ba8d74ecdfc89c217832fedphilippe   advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok );
238645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok || advised != start)
238745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
238845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
238945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* We have been advised that the mapping is allowable at the
239045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      specified address.  So hand it off to the kernel, and propagate
239145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      any resulting failure immediately. */
2392f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // DDD: #warning GrP fixme MAP_FIXED can clobber memory!
239345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sres = VG_(am_do_mmap_NO_NOTIFY)(
23948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj             start, length, prot, flags,
239545f4e7c91119c7d01a59f5e827c67841632c9314sewardj             fd, offset
239645f4e7c91119c7d01a59f5e827c67841632c9314sewardj          );
2397cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
239845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
239945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2400cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_Res(sres) != start) {
240145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* I don't think this can happen.  It means the kernel made a
240245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         fixed map succeed but not at the requested location.  Try to
240345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         repair the damage, then return saying the mapping failed. */
2404cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length );
240545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
240679048ce723a3463c70257ce647f04b111de71863sewardj   }
240779048ce723a3463c70257ce647f04b111de71863sewardj
240845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ok, the mapping succeeded.  Now notify the interval map. */
240945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
241045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind   = SkFileC;
241145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start  = start;
241245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end    = seg.start + VG_PGROUNDUP(length) - 1;
241345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.offset = offset;
241445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR   = toBool(prot & VKI_PROT_READ);
241545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW   = toBool(prot & VKI_PROT_WRITE);
241645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX   = toBool(prot & VKI_PROT_EXEC);
2417dad944add53e6361751c6832066c00c456854622njn   if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
241845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      seg.dev = dev;
241945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      seg.ino = ino;
2420f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom      seg.mode = mode;
242179048ce723a3463c70257ce647f04b111de71863sewardj   }
2422f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (name) {
24234ecd48360351f666f008148c12a24cbda455c6b1florian      seg.fnIdx = ML_(am_allocate_segname)( name );
2424f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   } else if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
24254ecd48360351f666f008148c12a24cbda455c6b1florian      seg.fnIdx = ML_(am_allocate_segname)( buf );
242679048ce723a3463c70257ce647f04b111de71863sewardj   }
242745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
242879048ce723a3463c70257ce647f04b111de71863sewardj
242945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
243045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sres;
243179048ce723a3463c70257ce647f04b111de71863sewardj}
243279048ce723a3463c70257ce647f04b111de71863sewardj
243379048ce723a3463c70257ce647f04b111de71863sewardj
243445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map anonymously at a fixed address for the client, and update
243545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   the segment array accordingly. */
2436de4a1d01951937632098a6cda45859afa587a06fsewardj
243745f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_anon_fixed_client) ( Addr start, SizeT length, UInt prot )
243898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge{
243945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes     sres;
244045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment   seg;
244145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr       advised;
244245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool       ok;
244345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   MapRequest req;
244445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
244545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Not allowable. */
244645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (length == 0 || !VG_IS_PAGE_ALIGNED(start))
244745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
244845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
244945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ask for an advisory.  If it's negative, fail immediately. */
245045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.rkind = MFixed;
245145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.start = start;
245245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.len   = length;
2453515e26933c61eed21ba8d74ecdfc89c217832fedphilippe   advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok );
245445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok || advised != start)
245545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
245645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
245745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* We have been advised that the mapping is allowable at the
245845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      specified address.  So hand it off to the kernel, and propagate
245945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      any resulting failure immediately. */
2460f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // DDD: #warning GrP fixme MAP_FIXED can clobber memory!
246145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sres = VG_(am_do_mmap_NO_NOTIFY)(
246245f4e7c91119c7d01a59f5e827c67841632c9314sewardj             start, length, prot,
246345f4e7c91119c7d01a59f5e827c67841632c9314sewardj             VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
246445f4e7c91119c7d01a59f5e827c67841632c9314sewardj             0, 0
246545f4e7c91119c7d01a59f5e827c67841632c9314sewardj          );
2466cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
246745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
246845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2469cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_Res(sres) != start) {
247045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* I don't think this can happen.  It means the kernel made a
247145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         fixed map succeed but not at the requested location.  Try to
247245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         repair the damage, then return saying the mapping failed. */
2473cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length );
247445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
247545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
247698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
247745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ok, the mapping succeeded.  Now notify the interval map. */
247845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
247945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind  = SkAnonC;
248045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start = start;
248145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end   = seg.start + VG_PGROUNDUP(length) - 1;
248245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR  = toBool(prot & VKI_PROT_READ);
248345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW  = toBool(prot & VKI_PROT_WRITE);
248445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX  = toBool(prot & VKI_PROT_EXEC);
248545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
248645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
248745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
248845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sres;
248998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
249098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
249198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
249245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map anonymously at an unconstrained address for the client, and
249345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   update the segment array accordingly.  */
249498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
2495a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic SysRes am_mmap_anon_float_client ( SizeT length, Int prot, Bool isCH )
249698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge{
249745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes     sres;
249845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment   seg;
249945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr       advised;
250045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool       ok;
250145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   MapRequest req;
250245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
250345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Not allowable. */
250445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (length == 0)
250545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
250645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
250745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ask for an advisory.  If it's negative, fail immediately. */
250845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.rkind = MAny;
250945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.start = 0;
251045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.len   = length;
2511515e26933c61eed21ba8d74ecdfc89c217832fedphilippe   advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok );
251245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok)
251345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
251445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
251545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* We have been advised that the mapping is allowable at the
251645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      advised address.  So hand it off to the kernel, and propagate
251745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      any resulting failure immediately. */
2518f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // DDD: #warning GrP fixme MAP_FIXED can clobber memory!
251945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sres = VG_(am_do_mmap_NO_NOTIFY)(
252045f4e7c91119c7d01a59f5e827c67841632c9314sewardj             advised, length, prot,
252145f4e7c91119c7d01a59f5e827c67841632c9314sewardj             VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
252245f4e7c91119c7d01a59f5e827c67841632c9314sewardj             0, 0
252345f4e7c91119c7d01a59f5e827c67841632c9314sewardj          );
2524cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
252545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
252645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2527cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_Res(sres) != advised) {
252845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* I don't think this can happen.  It means the kernel made a
252945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         fixed map succeed but not at the requested location.  Try to
253045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         repair the damage, then return saying the mapping failed. */
2531cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length );
253245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
2533e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   }
253445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
253545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ok, the mapping succeeded.  Now notify the interval map. */
253645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
253745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind  = SkAnonC;
253845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start = advised;
253945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end   = seg.start + VG_PGROUNDUP(length) - 1;
254045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR  = toBool(prot & VKI_PROT_READ);
254145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW  = toBool(prot & VKI_PROT_WRITE);
254245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX  = toBool(prot & VKI_PROT_EXEC);
2543a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   seg.isCH  = isCH;
254445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
254545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
254645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
254745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sres;
254898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
254998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
2550a0664b9ca67b594bd6f570a61d3301167a24750cElliott HughesSysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot )
2551a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes{
2552a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   return am_mmap_anon_float_client (length, prot, False /* isCH */);
2553a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes}
255445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
255545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map anonymously at an unconstrained address for V, and update the
255645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   segment array accordingly.  This is fundamentally how V allocates
255745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   itself more address space when needed. */
255845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
255945f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_anon_float_valgrind)( SizeT length )
25601024cf78e01e14eaa19ed6a8cd11beb50e6bc687sewardj{
256145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes     sres;
256245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment   seg;
256345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr       advised;
256445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool       ok;
256545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   MapRequest req;
256645f4e7c91119c7d01a59f5e827c67841632c9314sewardj
256745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Not allowable. */
256845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (length == 0)
256945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
257045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
257145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ask for an advisory.  If it's negative, fail immediately. */
257245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.rkind = MAny;
257345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.start = 0;
257445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.len   = length;
2575515e26933c61eed21ba8d74ecdfc89c217832fedphilippe   advised = VG_(am_get_advisory)( &req, False/*forClient*/, &ok );
257645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok)
257745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
257845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2579f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// On Darwin, for anonymous maps you can pass in a tag which is used by
2580f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// programs like vmmap for statistical purposes.
2581f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#ifndef VM_TAG_VALGRIND
2582f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#  define VM_TAG_VALGRIND 0
2583f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2584f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
258545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* We have been advised that the mapping is allowable at the
258645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      specified address.  So hand it off to the kernel, and propagate
258745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      any resulting failure immediately. */
2588f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* GrP fixme darwin: use advisory as a hint only, otherwise syscall in
2589f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      another thread can pre-empt our spot.  [At one point on the DARWIN
2590f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      branch the VKI_MAP_FIXED was commented out;  unclear if this is
2591f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      necessary or not given the second Darwin-only call that immediately
25923bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      follows if this one fails.  --njn]
25933bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      Also, an inner valgrind cannot observe the mmap syscalls done by
25943bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      the outer valgrind. The outer Valgrind might make the mmap
25953bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      fail here, as the inner valgrind believes that a segment is free,
25963bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      while it is in fact used by the outer valgrind.
25973bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      So, for an inner valgrind, similarly to DARWIN, if the fixed mmap
25983bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      fails, retry the mmap without map fixed.
25993bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      This is a kludge which on linux is only activated for the inner.
26003bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      The state of the inner aspacemgr is not made correct by this kludge
26013bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      and so a.o. VG_(am_do_sync_check) could fail.
26023bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      A proper solution implies a better collaboration between the
26033bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      inner and the outer (e.g. inner VG_(am_get_advisory) should do
26043bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      a client request to call the outer VG_(am_get_advisory). */
260545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sres = VG_(am_do_mmap_NO_NOTIFY)(
260645f4e7c91119c7d01a59f5e827c67841632c9314sewardj             advised, length,
260745f4e7c91119c7d01a59f5e827c67841632c9314sewardj             VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
260845f4e7c91119c7d01a59f5e827c67841632c9314sewardj             VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
2609f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             VM_TAG_VALGRIND, 0
261045f4e7c91119c7d01a59f5e827c67841632c9314sewardj          );
26113bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe#if defined(VGO_darwin) || defined(ENABLE_INNER)
26123bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe   /* Kludge on Darwin and inner linux if the fixed mmap failed. */
2613f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (sr_isError(sres)) {
2614f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       /* try again, ignoring the advisory */
2615f76d27a697a7b0bf3b84490baf60623fc96a23afnjn       sres = VG_(am_do_mmap_NO_NOTIFY)(
2616f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             0, length,
2617f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
2618f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             /*VKI_MAP_FIXED|*/VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
2619f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             VM_TAG_VALGRIND, 0
2620f76d27a697a7b0bf3b84490baf60623fc96a23afnjn          );
2621f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
2622f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
2623cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
262445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
262545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
26263bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe#if defined(VGO_linux) && !defined(ENABLE_INNER)
26273bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe   /* Doing the check only in linux not inner, as the below
26283bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe      check can fail when the kludge above has been used. */
2629cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_Res(sres) != advised) {
263045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* I don't think this can happen.  It means the kernel made a
263145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         fixed map succeed but not at the requested location.  Try to
263245f4e7c91119c7d01a59f5e827c67841632c9314sewardj         repair the damage, then return saying the mapping failed. */
2633cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length );
263445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
26351024cf78e01e14eaa19ed6a8cd11beb50e6bc687sewardj   }
2636f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif
263745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
263845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ok, the mapping succeeded.  Now notify the interval map. */
263945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
264045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind  = SkAnonV;
2641cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   seg.start = sr_Res(sres);
264245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end   = seg.start + VG_PGROUNDUP(length) - 1;
264345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR  = True;
264445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW  = True;
264545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX  = True;
264645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
264745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
264845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
264945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sres;
265098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
265198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
265245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Really just a wrapper around VG_(am_mmap_anon_float_valgrind). */
26531024cf78e01e14eaa19ed6a8cd11beb50e6bc687sewardj
265445f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid* VG_(am_shadow_alloc)(SizeT size)
265598abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge{
265645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes sres = VG_(am_mmap_anon_float_valgrind)( size );
2657cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   return sr_isError(sres) ? NULL : (void*)sr_Res(sres);
265845f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
265998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
266045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map a file at an unconstrained address for V, and update the
26613b290486cd4cd601b20e04340e593c9ed9717e5fsewardj   segment array accordingly. Use the provided flags */
266298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
26633b290486cd4cd601b20e04340e593c9ed9717e5fsewardjstatic SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot,
26643b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                                       UInt flags,
26653b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                                       Int fd, Off64T offset )
266645f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
266745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes     sres;
266845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment   seg;
266945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr       advised;
267045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool       ok;
267145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   MapRequest req;
2672419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   ULong      dev, ino;
2673f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom   UInt       mode;
267445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   HChar      buf[VKI_PATH_MAX];
267545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
267645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Not allowable. */
2677274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   if (length == 0 || !VG_IS_PAGE_ALIGNED(offset))
267845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
267945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
268045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ask for an advisory.  If it's negative, fail immediately. */
268145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.rkind = MAny;
268245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   req.start = 0;
26830eb0d5a73655b8ed1b6c93d7032311a5d102a8f0philippe   #if defined(VGA_arm) || defined(VGA_arm64) \
26840eb0d5a73655b8ed1b6c93d7032311a5d102a8f0philippe      || defined(VGA_mips32) || defined(VGA_mips64)
268553b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
268653b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   #else
268753b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
268853b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   #endif
268953b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   if ((VKI_SHMLBA > VKI_PAGE_SIZE) && (VKI_MAP_SHARED & flags)) {
269053b0d9a5e90ecd4e4b50489915c221c86734908fphilippe      /* arm-linux only. See ML_(generic_PRE_sys_shmat) and bug 290974 */
269153b0d9a5e90ecd4e4b50489915c221c86734908fphilippe      req.len = length + VKI_SHMLBA - VKI_PAGE_SIZE;
269253b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   } else {
269353b0d9a5e90ecd4e4b50489915c221c86734908fphilippe      req.len = length;
269453b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   }
2695515e26933c61eed21ba8d74ecdfc89c217832fedphilippe   advised = VG_(am_get_advisory)( &req, False/*forClient*/, &ok );
269645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!ok)
269745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
269853b0d9a5e90ecd4e4b50489915c221c86734908fphilippe   if ((VKI_SHMLBA > VKI_PAGE_SIZE) && (VKI_MAP_SHARED & flags))
269953b0d9a5e90ecd4e4b50489915c221c86734908fphilippe      advised = VG_ROUNDUP(advised, VKI_SHMLBA);
270045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
270145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* We have been advised that the mapping is allowable at the
270245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      specified address.  So hand it off to the kernel, and propagate
270345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      any resulting failure immediately. */
270445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   sres = VG_(am_do_mmap_NO_NOTIFY)(
270545f4e7c91119c7d01a59f5e827c67841632c9314sewardj             advised, length, prot,
27063b290486cd4cd601b20e04340e593c9ed9717e5fsewardj             flags,
270745f4e7c91119c7d01a59f5e827c67841632c9314sewardj             fd, offset
270845f4e7c91119c7d01a59f5e827c67841632c9314sewardj          );
2709cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
271045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
271145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
2712cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_Res(sres) != advised) {
271345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* I don't think this can happen.  It means the kernel made a
271445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         fixed map succeed but not at the requested location.  Try to
271545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         repair the damage, then return saying the mapping failed. */
2716cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length );
271745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Error)( VKI_EINVAL );
271845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
271998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
272045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Ok, the mapping succeeded.  Now notify the interval map. */
272145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
272245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind   = SkFileV;
2723cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   seg.start  = sr_Res(sres);
272445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end    = seg.start + VG_PGROUNDUP(length) - 1;
272545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.offset = offset;
272645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasR   = toBool(prot & VKI_PROT_READ);
272745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasW   = toBool(prot & VKI_PROT_WRITE);
272845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.hasX   = toBool(prot & VKI_PROT_EXEC);
2729dad944add53e6361751c6832066c00c456854622njn   if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
2730cf4ac71eeefa63bb2edc6b9ed09584612a3a7db0sewardj      seg.dev  = dev;
2731cf4ac71eeefa63bb2edc6b9ed09584612a3a7db0sewardj      seg.ino  = ino;
2732cf4ac71eeefa63bb2edc6b9ed09584612a3a7db0sewardj      seg.mode = mode;
273345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
2734dad944add53e6361751c6832066c00c456854622njn   if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
27354ecd48360351f666f008148c12a24cbda455c6b1florian      seg.fnIdx = ML_(am_allocate_segname)( buf );
273645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
273745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
273847c98a767e79e36511bf7b177a5b5d24930efd7csewardj
273945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
274045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sres;
274145f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
27423b290486cd4cd601b20e04340e593c9ed9717e5fsewardj/* Map privately a file at an unconstrained address for V, and update the
27433b290486cd4cd601b20e04340e593c9ed9717e5fsewardj   segment array accordingly.  This is used by V for transiently
27443b290486cd4cd601b20e04340e593c9ed9717e5fsewardj   mapping in object files to read their debug info.  */
27453b290486cd4cd601b20e04340e593c9ed9717e5fsewardj
27463b290486cd4cd601b20e04340e593c9ed9717e5fsewardjSysRes VG_(am_mmap_file_float_valgrind) ( SizeT length, UInt prot,
27473b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                          Int fd, Off64T offset )
27483b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{
27493b290486cd4cd601b20e04340e593c9ed9717e5fsewardj   return VG_(am_mmap_file_float_valgrind_flags) (length, prot,
27503b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                                  VKI_MAP_FIXED|VKI_MAP_PRIVATE,
27513b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                                  fd, offset );
27523b290486cd4cd601b20e04340e593c9ed9717e5fsewardj}
275347c98a767e79e36511bf7b177a5b5d24930efd7csewardj
2754d6633333a292fc9b64f04200d836b08f55889321sewardjSysRes VG_(am_shared_mmap_file_float_valgrind)
27553b290486cd4cd601b20e04340e593c9ed9717e5fsewardj   ( SizeT length, UInt prot, Int fd, Off64T offset )
27563b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{
27573b290486cd4cd601b20e04340e593c9ed9717e5fsewardj   return VG_(am_mmap_file_float_valgrind_flags) (length, prot,
27583b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                                  VKI_MAP_FIXED|VKI_MAP_SHARED,
27593b290486cd4cd601b20e04340e593c9ed9717e5fsewardj                                                  fd, offset );
27603b290486cd4cd601b20e04340e593c9ed9717e5fsewardj}
276198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
2762a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes/* Similar to VG_(am_mmap_anon_float_client) but also
27632fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   marks the segment as containing the client heap. This is for the benefit
27642fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   of the leak checker which needs to be able to identify such segments
27652fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   so as not to use them as sources of roots during leak checks. */
27662fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorianSysRes VG_(am_mmap_client_heap) ( SizeT length, Int prot )
27672fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian{
2768a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   return am_mmap_anon_float_client (length, prot, True /* isCH */);
27692fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian}
27702fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian
277145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- munmap helper --- --- */
277298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
277345f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic
277445f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes am_munmap_both_wrk ( /*OUT*/Bool* need_discard,
277545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                            Addr start, SizeT len, Bool forClient )
277645f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
277745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool   d;
277845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes sres;
277998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
2780ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   /* Be safe with this regardless of return path. */
2781ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   *need_discard = False;
2782ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes
278345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!VG_IS_PAGE_ALIGNED(start))
278445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
278547c98a767e79e36511bf7b177a5b5d24930efd7csewardj
278645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0) {
278745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      *need_discard = False;
278845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return VG_(mk_SysRes_Success)( 0 );
2789e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   }
279098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
279145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (start + len < len)
279245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      goto eINVAL;
2793a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj
279413bfd85dfab2cd301c92e308b274ebd17de830d2njn   len = VG_PGROUNDUP(len);
279545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start));
279645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(len));
279798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
279845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (forClient) {
279945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (!VG_(am_is_valid_for_client_or_free_or_resvn)
280045f4e7c91119c7d01a59f5e827c67841632c9314sewardj            ( start, len, VKI_PROT_NONE ))
280145f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto eINVAL;
280245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else {
2803adfff76735ea5bca870dec8f382b225728e1b32dphilippe      if (!VG_(am_is_valid_for_valgrind)
2804adfff76735ea5bca870dec8f382b225728e1b32dphilippe            ( start, len, VKI_PROT_NONE ))
280545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         goto eINVAL;
280698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge   }
280798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
280845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   d = any_Ts_in_range( start, len );
280998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
2810297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   sres = ML_(am_do_munmap_NO_NOTIFY)( start, len );
2811cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres))
281245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return sres;
281398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
281445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(am_notify_munmap)( start, len );
281545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
281645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   *need_discard = d;
281745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return sres;
281898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
281945f4e7c91119c7d01a59f5e827c67841632c9314sewardj  eINVAL:
282045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return VG_(mk_SysRes_Error)( VKI_EINVAL );
282145f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
282298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
282345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Unmap the given address range and update the segment array
282445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   accordingly.  This fails if the range isn't valid for the client.
282545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   If *need_discard is True after a successful return, the caller
282645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   should immediately discard translations from the specified address
282745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   range. */
282898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
282945f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard,
283045f4e7c91119c7d01a59f5e827c67841632c9314sewardj                              Addr start, SizeT len )
283145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
283245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return am_munmap_both_wrk( need_discard, start, len, True/*client*/ );
2833de4a1d01951937632098a6cda45859afa587a06fsewardj}
2834de4a1d01951937632098a6cda45859afa587a06fsewardj
283545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Unmap the given address range and update the segment array
283645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   accordingly.  This fails if the range isn't valid for valgrind. */
2837de4a1d01951937632098a6cda45859afa587a06fsewardj
283845f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_munmap_valgrind)( Addr start, SizeT len )
283945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
284045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Bool need_discard;
284145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes r = am_munmap_both_wrk( &need_discard,
284245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                  start, len, False/*valgrind*/ );
284345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* If this assertion fails, it means we allowed translations to be
284445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      made from a V-owned section.  Which shouldn't happen. */
2845cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (!sr_isError(r))
284645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(!need_discard);
284745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return r;
284898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
284998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
285045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Let (start,len) denote an area within a single Valgrind-owned
285145f4e7c91119c7d01a59f5e827c67841632c9314sewardj  segment (anon or file).  Change the ownership of [start, start+len)
285245f4e7c91119c7d01a59f5e827c67841632c9314sewardj  to the client instead.  Fails if (start,len) does not denote a
285345f4e7c91119c7d01a59f5e827c67841632c9314sewardj  suitable segment. */
285445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
285545f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len )
2856de4a1d01951937632098a6cda45859afa587a06fsewardj{
285745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int i, iLo, iHi;
2858de4a1d01951937632098a6cda45859afa587a06fsewardj
285945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (len == 0)
286045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return True;
286145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (start + len < start)
286245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
286345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!VG_IS_PAGE_ALIGNED(start) || !VG_IS_PAGE_ALIGNED(len))
286445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
2865e517b80ab9ac4da3544fdb905ce76fcabf92da97sewardj
286645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   i = find_nsegment_idx(start);
286745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nsegments[i].kind != SkFileV && nsegments[i].kind != SkAnonV)
286845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
286945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (start+len-1 > nsegments[i].end)
287045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
287198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
287245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(start >= nsegments[i].start);
287345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(start+len-1 <= nsegments[i].end);
287445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
287545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* This scheme is like how mprotect works: split the to-be-changed
287645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      range into its own segment(s), then mess with them (it).  There
287745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      should be only one. */
287845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi );
287945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(iLo == iHi);
288045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   switch (nsegments[iLo].kind) {
288145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkFileV: nsegments[iLo].kind = SkFileC; break;
288245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      case SkAnonV: nsegments[iLo].kind = SkAnonC; break;
288345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      default: aspacem_assert(0); /* can't happen - guarded above */
288445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
288598abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
288645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   preen_nsegments();
288745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return True;
288845f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
2889548be6d64c58729588a559b1512ad7625bc1b86esewardj
28902fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian/* Set the 'hasT' bit on the segment containing ADDR indicating that
28912fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   translations have or may have been taken from this segment. ADDR is
28922fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   expected to belong to a client segment. */
28932fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorianvoid VG_(am_set_segment_hasT)( Addr addr )
2894716f31ac50be6070a96b490d0b0bbd39b8e77342sewardj{
28952fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   Int i = find_nsegment_idx(addr);
28962fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   SegKind kind = nsegments[i].kind;
28972fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   aspacem_assert(kind == SkAnonC || kind == SkFileC || kind == SkShmC);
28982fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian   nsegments[i].hasT = True;
2899716f31ac50be6070a96b490d0b0bbd39b8e77342sewardj}
2900716f31ac50be6070a96b490d0b0bbd39b8e77342sewardj
290198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
290245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- --- reservations --- --- --- */
2903de4a1d01951937632098a6cda45859afa587a06fsewardj
290445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Create a reservation from START .. START+LENGTH-1, with the given
290545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   ShrinkMode.  When checking whether the reservation can be created,
290645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   also ensure that at least abs(EXTRA) extra free bytes will remain
290745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   above (> 0) or below (< 0) the reservation.
290898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
290945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   The reservation will only be created if it, plus the extra-zone,
291045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   falls entirely within a single free segment.  The returned Bool
291145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   indicates whether the creation succeeded. */
291279048ce723a3463c70257ce647f04b111de71863sewardj
291345f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_create_reservation) ( Addr start, SizeT length,
291445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                  ShrinkMode smode, SSizeT extra )
291545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
291645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int      startI, endI;
291745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   NSegment seg;
2918e517b80ab9ac4da3544fdb905ce76fcabf92da97sewardj
291945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* start and end, not taking into account the extra space. */
292045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr start1 = start;
292145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr end1   = start + length - 1;
2922e517b80ab9ac4da3544fdb905ce76fcabf92da97sewardj
292345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* start and end, taking into account the extra space. */
292445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr start2 = start1;
292545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr end2   = end1;
292698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
292745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (extra < 0) start2 += extra; // this moves it down :-)
292845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (extra > 0) end2 += extra;
292998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
293045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start));
293145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start+length));
293245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(start2));
293345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(end2+1));
293498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
293545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   startI = find_nsegment_idx( start2 );
293645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   endI = find_nsegment_idx( end2 );
2937548be6d64c58729588a559b1512ad7625bc1b86esewardj
293845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* If the start and end points don't fall within the same (free)
293945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      segment, we're hosed.  This does rely on the assumption that all
294045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      mergeable adjacent segments can be merged, but add_segment()
294145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      should ensure that. */
294245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (startI != endI)
294345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
2944548be6d64c58729588a559b1512ad7625bc1b86esewardj
294545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (nsegments[startI].kind != SkFree)
294645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
2947548be6d64c58729588a559b1512ad7625bc1b86esewardj
294845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Looks good - make the reservation. */
294945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(nsegments[startI].start <= start2);
295045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(end2 <= nsegments[startI].end);
2951548be6d64c58729588a559b1512ad7625bc1b86esewardj
295245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
295345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.kind  = SkResvn;
295445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start = start1;  /* NB: extra space is not included in the
295545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                           reservation. */
295645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end   = end1;
295745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.smode = smode;
295845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
2959548be6d64c58729588a559b1512ad7625bc1b86esewardj
296045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
296145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return True;
296245f4e7c91119c7d01a59f5e827c67841632c9314sewardj}
2963548be6d64c58729588a559b1512ad7625bc1b86esewardj
2964548be6d64c58729588a559b1512ad7625bc1b86esewardj
2965888b8159535580b30550f99cb7361f62edd83100florian/* ADDR is the start address of an anonymous client mapping.  This fn extends
2966888b8159535580b30550f99cb7361f62edd83100florian   the mapping by DELTA bytes, taking the space from a reservation section
296745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   which must be adjacent.  If DELTA is positive, the segment is
296845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   extended forwards in the address space, and the reservation must be
296945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   the next one along.  If DELTA is negative, the segment is extended
297045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   backwards in the address space and the reservation must be the
29716684d2afc25363b29a9ce4281050161d91baeebfsewardj   previous one.  DELTA must be page aligned.  abs(DELTA) must not
29726684d2afc25363b29a9ce4281050161d91baeebfsewardj   exceed the size of the reservation segment minus one page, that is,
29736684d2afc25363b29a9ce4281050161d91baeebfsewardj   the reservation segment after the operation must be at least one
2974888b8159535580b30550f99cb7361f62edd83100florian   page long. The function returns a pointer to the resized segment. */
2975548be6d64c58729588a559b1512ad7625bc1b86esewardj
2976888b8159535580b30550f99cb7361f62edd83100florianconst NSegment *VG_(am_extend_into_adjacent_reservation_client)( Addr addr,
297715fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian                                                                 SSizeT delta,
297815fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian                                                                 Bool *overflow)
297945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
298045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int    segA, segR;
298145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   UInt   prot;
298245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes sres;
2983548be6d64c58729588a559b1512ad7625bc1b86esewardj
298415fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian   *overflow = False;
298515fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian
2986888b8159535580b30550f99cb7361f62edd83100florian   segA = find_nsegment_idx(addr);
2987888b8159535580b30550f99cb7361f62edd83100florian   aspacem_assert(nsegments[segA].kind == SkAnonC);
298845f4e7c91119c7d01a59f5e827c67841632c9314sewardj
298945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (delta == 0)
2990888b8159535580b30550f99cb7361f62edd83100florian      return nsegments + segA;
299145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
299245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   prot =   (nsegments[segA].hasR ? VKI_PROT_READ : 0)
299345f4e7c91119c7d01a59f5e827c67841632c9314sewardj          | (nsegments[segA].hasW ? VKI_PROT_WRITE : 0)
299445f4e7c91119c7d01a59f5e827c67841632c9314sewardj          | (nsegments[segA].hasX ? VKI_PROT_EXEC : 0);
299545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
299645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   aspacem_assert(VG_IS_PAGE_ALIGNED(delta<0 ? -delta : delta));
299745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
299845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (delta > 0) {
299945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
300045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Extending the segment forwards. */
300145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      segR = segA+1;
300245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (segR >= nsegments_used
300345f4e7c91119c7d01a59f5e827c67841632c9314sewardj          || nsegments[segR].kind != SkResvn
300415fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian          || nsegments[segR].smode != SmLower)
300515fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian         return NULL;
300615fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian
300715fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian      if (delta + VKI_PAGE_SIZE
300815fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian                > (nsegments[segR].end - nsegments[segR].start + 1)) {
300915fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian         *overflow = True;
301015fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian         return NULL;
301115fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian      }
301245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
301345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Extend the kernel's mapping. */
3014f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // DDD: #warning GrP fixme MAP_FIXED can clobber memory!
301545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_do_mmap_NO_NOTIFY)(
301645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                nsegments[segR].start, delta,
301745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                prot,
301845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
301945f4e7c91119c7d01a59f5e827c67841632c9314sewardj                0, 0
302045f4e7c91119c7d01a59f5e827c67841632c9314sewardj             );
3021cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres))
3022888b8159535580b30550f99cb7361f62edd83100florian         return NULL; /* kernel bug if this happens? */
3023cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_Res(sres) != nsegments[segR].start) {
302445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* kernel bug if this happens? */
3025cda2f0fbda4c4b2644babc830244be8aed95de1dnjn        (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta );
3026888b8159535580b30550f99cb7361f62edd83100florian        return NULL;
3027548be6d64c58729588a559b1512ad7625bc1b86esewardj      }
3028548be6d64c58729588a559b1512ad7625bc1b86esewardj
302945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Ok, success with the kernel.  Update our structures. */
30303bfb914e76943b35e96bbaead678c2c96f3380edflorian      nsegments[segR].start += delta;
30313bfb914e76943b35e96bbaead678c2c96f3380edflorian      nsegments[segA].end += delta;
30323bfb914e76943b35e96bbaead678c2c96f3380edflorian      aspacem_assert(nsegments[segR].start <= nsegments[segR].end);
3033548be6d64c58729588a559b1512ad7625bc1b86esewardj
3034548be6d64c58729588a559b1512ad7625bc1b86esewardj   } else {
3035548be6d64c58729588a559b1512ad7625bc1b86esewardj
303645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Extending the segment backwards. */
303745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      delta = -delta;
303845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      aspacem_assert(delta > 0);
303945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
304045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      segR = segA-1;
304145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      if (segR < 0
304245f4e7c91119c7d01a59f5e827c67841632c9314sewardj          || nsegments[segR].kind != SkResvn
304315fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian          || nsegments[segR].smode != SmUpper)
304415fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian         return NULL;
304515fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian
304615fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian      if (delta + VKI_PAGE_SIZE
304715fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian                > (nsegments[segR].end - nsegments[segR].start + 1)) {
304815fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian         *overflow = True;
304915fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian         return NULL;
305015fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian      }
305145f4e7c91119c7d01a59f5e827c67841632c9314sewardj
305245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Extend the kernel's mapping. */
3053f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      // DDD: #warning GrP fixme MAP_FIXED can clobber memory!
305445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_do_mmap_NO_NOTIFY)(
305545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                nsegments[segA].start-delta, delta,
305645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                prot,
305745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
305845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                0, 0
305945f4e7c91119c7d01a59f5e827c67841632c9314sewardj             );
3060cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres))
3061888b8159535580b30550f99cb7361f62edd83100florian         return NULL; /* kernel bug if this happens? */
3062cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_Res(sres) != nsegments[segA].start-delta) {
306345f4e7c91119c7d01a59f5e827c67841632c9314sewardj         /* kernel bug if this happens? */
3064cda2f0fbda4c4b2644babc830244be8aed95de1dnjn        (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta );
3065888b8159535580b30550f99cb7361f62edd83100florian        return NULL;
306645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
3067548be6d64c58729588a559b1512ad7625bc1b86esewardj
306845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* Ok, success with the kernel.  Update our structures. */
30693bfb914e76943b35e96bbaead678c2c96f3380edflorian      nsegments[segR].end -= delta;
30703bfb914e76943b35e96bbaead678c2c96f3380edflorian      nsegments[segA].start -= delta;
30713bfb914e76943b35e96bbaead678c2c96f3380edflorian      aspacem_assert(nsegments[segR].start <= nsegments[segR].end);
3072b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj   }
3073b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
307445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
3075888b8159535580b30550f99cb7361f62edd83100florian   return nsegments + segA;
307698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
307798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
307879048ce723a3463c70257ce647f04b111de71863sewardj
307945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- --- resizing/move a mapping --- --- --- */
3080646c6aa268d4f1e524f2a9b721eef7a62d87046dthughes
3081f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if HAVE_MREMAP
3082f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3083dd7318bea2a008f15085e12e026a78a6802e2e9cflorian/* This function grows a client mapping in place into an adjacent free segment.
3084dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   ADDR is the client mapping's start address and DELTA, which must be page
3085dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aligned, is the growth amount. The function returns a pointer to the
3086dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   resized segment. The function is used in support of mremap. */
3087dd7318bea2a008f15085e12e026a78a6802e2e9cflorianconst NSegment *VG_(am_extend_map_client)( Addr addr, SizeT delta )
308845f4e7c91119c7d01a59f5e827c67841632c9314sewardj{
308945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Addr     xStart;
309045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes   sres;
30919aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes
309263a622f4da0254c435348f2c78b31aa66f4549c8sewardj   if (0)
309363a622f4da0254c435348f2c78b31aa66f4549c8sewardj      VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) BEFORE");
309463a622f4da0254c435348f2c78b31aa66f4549c8sewardj
3095dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   /* Get the client segment */
3096dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   Int ix = find_nsegment_idx(addr);
3097dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aspacem_assert(ix >= 0 && ix < nsegments_used);
30989aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes
3099dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   NSegment *seg = nsegments + ix;
3100dd7318bea2a008f15085e12e026a78a6802e2e9cflorian
31017a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian   aspacem_assert(seg->kind == SkFileC || seg->kind == SkAnonC ||
31027a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian                  seg->kind == SkShmC);
3103dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aspacem_assert(delta > 0 && VG_IS_PAGE_ALIGNED(delta)) ;
3104394790db0f8e9ce913e12df8555af7155b9aa0bdsewardj
310545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   xStart = seg->end+1;
3106dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aspacem_assert(xStart + delta >= delta);   // no wrap-around
31079aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes
3108dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   /* The segment following the client segment must be a free segment and
3109dd7318bea2a008f15085e12e026a78a6802e2e9cflorian      it must be large enough to cover the additional memory. */
3110dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   NSegment *segf = seg + 1;
3111dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aspacem_assert(segf->kind == SkFree);
3112dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aspacem_assert(segf->start == xStart);
3113dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   aspacem_assert(xStart + delta - 1 <= segf->end);
3114dd7318bea2a008f15085e12e026a78a6802e2e9cflorian
3115dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   SizeT seg_old_len = seg->end + 1 - seg->start;
31169aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes
311745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
3118297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   sres = ML_(am_do_extend_mapping_NO_NOTIFY)( seg->start,
3119297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj                                               seg_old_len,
3120297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj                                               seg_old_len + delta );
3121cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
312245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      AM_SANITY_CHECK;
3123dd7318bea2a008f15085e12e026a78a6802e2e9cflorian      return NULL;
312463a622f4da0254c435348f2c78b31aa66f4549c8sewardj   } else {
312563a622f4da0254c435348f2c78b31aa66f4549c8sewardj      /* the area must not have moved */
3126cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      aspacem_assert(sr_Res(sres) == seg->start);
31279aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes   }
31289aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes
3129dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   NSegment seg_copy = *seg;
313045f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg_copy.end += delta;
313145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg_copy );
3132548be6d64c58729588a559b1512ad7625bc1b86esewardj
313363a622f4da0254c435348f2c78b31aa66f4549c8sewardj   if (0)
313463a622f4da0254c435348f2c78b31aa66f4549c8sewardj      VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) AFTER");
313563a622f4da0254c435348f2c78b31aa66f4549c8sewardj
313645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
3137dd7318bea2a008f15085e12e026a78a6802e2e9cflorian   return nsegments + find_nsegment_idx(addr);
3138548be6d64c58729588a559b1512ad7625bc1b86esewardj}
3139548be6d64c58729588a559b1512ad7625bc1b86esewardj
3140548be6d64c58729588a559b1512ad7625bc1b86esewardj
314145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Remap the old address range to the new address range.  Fails if any
314245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   parameter is not page aligned, if the either size is zero, if any
314345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   wraparound is implied, if the old address range does not fall
314445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   entirely within a single segment, if the new address range overlaps
314545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   with the old one, or if the old address range is not a valid client
314645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   mapping.  If *need_discard is True after a successful return, the
314745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   caller should immediately discard translations from both specified
314845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   address ranges.  */
3149b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
315045f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
315145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                        Addr old_addr, SizeT old_len,
315245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                        Addr new_addr, SizeT new_len )
3153855d93d2e9940890b28874520fa4c1677bf825e2jsgf{
315445f4e7c91119c7d01a59f5e827c67841632c9314sewardj   Int      iLo, iHi;
315545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   SysRes   sres;
3156fcb3bc99945217eb66980488b933a6b65dc2f091tom   NSegment seg;
3157855d93d2e9940890b28874520fa4c1677bf825e2jsgf
315845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (old_len == 0 || new_len == 0)
315945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
3160b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
316145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (!VG_IS_PAGE_ALIGNED(old_addr) || !VG_IS_PAGE_ALIGNED(old_len)
316245f4e7c91119c7d01a59f5e827c67841632c9314sewardj       || !VG_IS_PAGE_ALIGNED(new_addr) || !VG_IS_PAGE_ALIGNED(new_len))
316345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
3164b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
316545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (old_addr + old_len < old_addr
316645f4e7c91119c7d01a59f5e827c67841632c9314sewardj       || new_addr + new_len < new_addr)
316745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
3168b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
316945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (old_addr + old_len - 1 < new_addr
317045f4e7c91119c7d01a59f5e827c67841632c9314sewardj       || new_addr + new_len - 1 < old_addr) {
317145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      /* no overlap */
317245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   } else
317345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
3174855d93d2e9940890b28874520fa4c1677bf825e2jsgf
317545f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iLo = find_nsegment_idx( old_addr );
317645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   iHi = find_nsegment_idx( old_addr + old_len - 1 );
317745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   if (iLo != iHi)
317845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
3179b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj
31807a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian   if (nsegments[iLo].kind != SkFileC && nsegments[iLo].kind != SkAnonC &&
31817a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian       nsegments[iLo].kind != SkShmC)
318245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
318398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
3184297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   sres = ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY)
3185297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj             ( old_addr, old_len, new_addr, new_len );
3186cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(sres)) {
318745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      AM_SANITY_CHECK;
318845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      return False;
3189ee2de2c04815768bd994d3c341e736eca1e72175sewardj   } else {
3190cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      aspacem_assert(sr_Res(sres) == new_addr);
319145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   }
319286f12dca3206f958abe000ff8c7de58098e0897cnjn
319345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   *need_discard = any_Ts_in_range( old_addr, old_len )
319445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                   || any_Ts_in_range( new_addr, new_len );
319586f12dca3206f958abe000ff8c7de58098e0897cnjn
3196fcb3bc99945217eb66980488b933a6b65dc2f091tom   seg = nsegments[iLo];
3197fcb3bc99945217eb66980488b933a6b65dc2f091tom
3198fcb3bc99945217eb66980488b933a6b65dc2f091tom   /* Mark the new area based on the old seg. */
3199fcb3bc99945217eb66980488b933a6b65dc2f091tom   if (seg.kind == SkFileC) {
3200fcb3bc99945217eb66980488b933a6b65dc2f091tom      seg.offset += ((ULong)old_addr) - ((ULong)seg.start);
3201fcb3bc99945217eb66980488b933a6b65dc2f091tom   }
3202fcb3bc99945217eb66980488b933a6b65dc2f091tom   seg.start = new_addr;
3203fcb3bc99945217eb66980488b933a6b65dc2f091tom   seg.end   = new_addr + new_len - 1;
3204fcb3bc99945217eb66980488b933a6b65dc2f091tom   add_segment( &seg );
320586f12dca3206f958abe000ff8c7de58098e0897cnjn
320645f4e7c91119c7d01a59f5e827c67841632c9314sewardj   /* Create a free hole in the old location. */
320745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   init_nsegment( &seg );
320845f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.start = old_addr;
320945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   seg.end   = old_addr + old_len - 1;
3210613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj   /* See comments in VG_(am_notify_munmap) about this SkResvn vs
3211613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      SkFree thing. */
3212613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj   if (old_addr > aspacem_maxAddr
3213613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj       && /* check previous comparison is meaningful */
3214613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj          aspacem_maxAddr < Addr_MAX)
3215613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      seg.kind = SkResvn;
3216613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj   else
3217613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj      seg.kind = SkFree;
3218613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj
321945f4e7c91119c7d01a59f5e827c67841632c9314sewardj   add_segment( &seg );
322086f12dca3206f958abe000ff8c7de58098e0897cnjn
322145f4e7c91119c7d01a59f5e827c67841632c9314sewardj   AM_SANITY_CHECK;
322245f4e7c91119c7d01a59f5e827c67841632c9314sewardj   return True;
322398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge}
322498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge
3225f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif // HAVE_MREMAP
3226f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3227f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3228c401ae7ea8e709040d70a2ea6e2e44979aa90ac0bart#if defined(VGO_linux)
3229c401ae7ea8e709040d70a2ea6e2e44979aa90ac0bart
323045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/
323145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*---                                                           ---*/
3232cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- A simple parser for /proc/self/maps on Linux 2.4.X/2.6.X. ---*/
3233cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- Almost completely independent of the stuff above.  The    ---*/
3234cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- only function it 'exports' to the code above this comment ---*/
3235cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- is parse_procselfmaps.                                    ---*/
3236cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*---                                                           ---*/
3237cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*-----------------------------------------------------------------*/
3238cb249ab3febb3757a0b0582be21952efacf415e5sewardj
323938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------BEGIN-procmaps-parser-for-Linux--------------------------*/
324038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
3241cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Size of a smallish table used to read /proc/self/map entries. */
3242cb249ab3febb3757a0b0582be21952efacf415e5sewardj#define M_PROCMAP_BUF 100000
3243cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3244cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* static ... to keep it out of the stack frame. */
3245dbb3584f591710a15a437918c0fc27e300993566florianstatic HChar procmap_buf[M_PROCMAP_BUF];
3246cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3247cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Records length of /proc/self/maps read into procmap_buf. */
3248cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic Int  buf_n_tot;
3249cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3250cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Helper fns. */
3251cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3252dbb3584f591710a15a437918c0fc27e300993566florianstatic Int hexdigit ( HChar c )
3253cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3254cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (c >= '0' && c <= '9') return (Int)(c - '0');
3255cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (c >= 'a' && c <= 'f') return 10 + (Int)(c - 'a');
3256cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (c >= 'A' && c <= 'F') return 10 + (Int)(c - 'A');
3257cb249ab3febb3757a0b0582be21952efacf415e5sewardj   return -1;
3258cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3259cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3260dbb3584f591710a15a437918c0fc27e300993566florianstatic Int decdigit ( HChar c )
3261cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3262cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (c >= '0' && c <= '9') return (Int)(c - '0');
3263cb249ab3febb3757a0b0582be21952efacf415e5sewardj   return -1;
3264cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3265cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3266dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readchar ( const HChar* buf, HChar* ch )
3267cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3268cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (*buf == 0) return 0;
3269cb249ab3febb3757a0b0582be21952efacf415e5sewardj   *ch = *buf;
3270cb249ab3febb3757a0b0582be21952efacf415e5sewardj   return 1;
3271cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3272cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3273dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readhex ( const HChar* buf, UWord* val )
3274cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3275274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   /* Read a word-sized hex number. */
3276274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   Int n = 0;
3277274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   *val = 0;
3278274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   while (hexdigit(*buf) >= 0) {
3279274461dcb67f680196c97e8afb7028a79b97dcb7sewardj      *val = (*val << 4) + hexdigit(*buf);
3280274461dcb67f680196c97e8afb7028a79b97dcb7sewardj      n++; buf++;
3281274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   }
3282274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   return n;
3283274461dcb67f680196c97e8afb7028a79b97dcb7sewardj}
3284274461dcb67f680196c97e8afb7028a79b97dcb7sewardj
3285dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readhex64 ( const HChar* buf, ULong* val )
3286274461dcb67f680196c97e8afb7028a79b97dcb7sewardj{
3287274461dcb67f680196c97e8afb7028a79b97dcb7sewardj   /* Read a potentially 64-bit hex number. */
3288cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Int n = 0;
3289cb249ab3febb3757a0b0582be21952efacf415e5sewardj   *val = 0;
3290cb249ab3febb3757a0b0582be21952efacf415e5sewardj   while (hexdigit(*buf) >= 0) {
3291cb249ab3febb3757a0b0582be21952efacf415e5sewardj      *val = (*val << 4) + hexdigit(*buf);
3292cb249ab3febb3757a0b0582be21952efacf415e5sewardj      n++; buf++;
3293cb249ab3febb3757a0b0582be21952efacf415e5sewardj   }
3294cb249ab3febb3757a0b0582be21952efacf415e5sewardj   return n;
3295cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3296cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3297dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readdec64 ( const HChar* buf, ULong* val )
3298cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3299cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Int n = 0;
3300cb249ab3febb3757a0b0582be21952efacf415e5sewardj   *val = 0;
330154212b6475e26755d9ecf452b9cc44fbc5772b7eflorian   while (decdigit(*buf) >= 0) {
3302cb249ab3febb3757a0b0582be21952efacf415e5sewardj      *val = (*val * 10) + decdigit(*buf);
3303cb249ab3febb3757a0b0582be21952efacf415e5sewardj      n++; buf++;
3304cb249ab3febb3757a0b0582be21952efacf415e5sewardj   }
3305cb249ab3febb3757a0b0582be21952efacf415e5sewardj   return n;
3306cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3307cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3308cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3309cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Get the contents of /proc/self/maps into a static buffer.  If
3310cb249ab3febb3757a0b0582be21952efacf415e5sewardj   there's a syntax error, it won't fit, or other failure, just
3311cb249ab3febb3757a0b0582be21952efacf415e5sewardj   abort. */
3312cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3313cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic void read_procselfmaps_into_buf ( void )
3314cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3315cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Int    n_chunk;
3316cb249ab3febb3757a0b0582be21952efacf415e5sewardj   SysRes fd;
3317cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3318cb249ab3febb3757a0b0582be21952efacf415e5sewardj   /* Read the initial memory mapping from the /proc filesystem. */
3319297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj   fd = ML_(am_open)( "/proc/self/maps", VKI_O_RDONLY, 0 );
3320cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   if (sr_isError(fd))
3321297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj      ML_(am_barf)("can't open /proc/self/maps");
3322cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3323cb249ab3febb3757a0b0582be21952efacf415e5sewardj   buf_n_tot = 0;
3324cb249ab3febb3757a0b0582be21952efacf415e5sewardj   do {
3325cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      n_chunk = ML_(am_read)( sr_Res(fd), &procmap_buf[buf_n_tot],
3326cb249ab3febb3757a0b0582be21952efacf415e5sewardj                              M_PROCMAP_BUF - buf_n_tot );
3327297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj      if (n_chunk >= 0)
3328297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj         buf_n_tot += n_chunk;
3329cb249ab3febb3757a0b0582be21952efacf415e5sewardj   } while ( n_chunk > 0 && buf_n_tot < M_PROCMAP_BUF );
3330cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3331cda2f0fbda4c4b2644babc830244be8aed95de1dnjn   ML_(am_close)(sr_Res(fd));
3332cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3333cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (buf_n_tot >= M_PROCMAP_BUF-5)
3334297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj      ML_(am_barf_toolow)("M_PROCMAP_BUF");
3335cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (buf_n_tot == 0)
3336297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj      ML_(am_barf)("I/O error on /proc/self/maps");
3337cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3338cb249ab3febb3757a0b0582be21952efacf415e5sewardj   procmap_buf[buf_n_tot] = 0;
3339cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3340cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3341cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Parse /proc/self/maps.  For each map entry, call
3342cb249ab3febb3757a0b0582be21952efacf415e5sewardj   record_mapping, passing it, in this order:
3343cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3344cb249ab3febb3757a0b0582be21952efacf415e5sewardj      start address in memory
3345cb249ab3febb3757a0b0582be21952efacf415e5sewardj      length
3346cb249ab3febb3757a0b0582be21952efacf415e5sewardj      page protections (using the VKI_PROT_* flags)
3347cb249ab3febb3757a0b0582be21952efacf415e5sewardj      mapped file device and inode
3348cb249ab3febb3757a0b0582be21952efacf415e5sewardj      offset in file, or zero if no file
3349cb249ab3febb3757a0b0582be21952efacf415e5sewardj      filename, zero terminated, or NULL if no file
3350cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3351cb249ab3febb3757a0b0582be21952efacf415e5sewardj   So the sig of the called fn might be
3352cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3353cb249ab3febb3757a0b0582be21952efacf415e5sewardj      void (*record_mapping)( Addr start, SizeT size, UInt prot,
3354cb249ab3febb3757a0b0582be21952efacf415e5sewardj			      UInt dev, UInt info,
3355cb249ab3febb3757a0b0582be21952efacf415e5sewardj                              ULong foffset, UChar* filename )
3356cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3357cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Note that the supplied filename is transiently stored; record_mapping
3358cb249ab3febb3757a0b0582be21952efacf415e5sewardj   should make a copy if it wants to keep it.
3359cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3360cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Nb: it is important that this function does not alter the contents of
3361cb249ab3febb3757a0b0582be21952efacf415e5sewardj       procmap_buf!
3362cb249ab3febb3757a0b0582be21952efacf415e5sewardj*/
3363cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic void parse_procselfmaps (
3364cb249ab3febb3757a0b0582be21952efacf415e5sewardj      void (*record_mapping)( Addr addr, SizeT len, UInt prot,
3365c4431bfe04c7490ea2d74939d222d87f13f30960njn                              ULong dev, ULong ino, Off64T offset,
3366dbb3584f591710a15a437918c0fc27e300993566florian                              const HChar* filename ),
3367cb249ab3febb3757a0b0582be21952efacf415e5sewardj      void (*record_gap)( Addr addr, SizeT len )
3368cb249ab3febb3757a0b0582be21952efacf415e5sewardj   )
3369cb249ab3febb3757a0b0582be21952efacf415e5sewardj{
3370cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Int    i, j, i_eol;
3371cb249ab3febb3757a0b0582be21952efacf415e5sewardj   Addr   start, endPlusOne, gapStart;
3372dbb3584f591710a15a437918c0fc27e300993566florian   HChar* filename;
3373dbb3584f591710a15a437918c0fc27e300993566florian   HChar  rr, ww, xx, pp, ch, tmp;
3374419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   UInt	  prot;
3375419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   UWord  maj, min;
3376419060073e7943846cc9e0bcdcb25258d90da2dcsewardj   ULong  foffset, dev, ino;
3377cb249ab3febb3757a0b0582be21952efacf415e5sewardj
33784c3faae4aa73a0693c66a24daccf8bc0a0e421f7sewardj   foffset = ino = 0; /* keep gcc-4.1.0 happy */
33794c3faae4aa73a0693c66a24daccf8bc0a0e421f7sewardj
3380cb249ab3febb3757a0b0582be21952efacf415e5sewardj   read_procselfmaps_into_buf();
3381cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3382cb249ab3febb3757a0b0582be21952efacf415e5sewardj   aspacem_assert('\0' != procmap_buf[0] && 0 != buf_n_tot);
3383cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3384cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (0)
3385cb249ab3febb3757a0b0582be21952efacf415e5sewardj      VG_(debugLog)(0, "procselfmaps", "raw:\n%s\n", procmap_buf);
3386cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3387cb249ab3febb3757a0b0582be21952efacf415e5sewardj   /* Ok, it's safely aboard.  Parse the entries. */
3388cb249ab3febb3757a0b0582be21952efacf415e5sewardj   i = 0;
3389cb249ab3febb3757a0b0582be21952efacf415e5sewardj   gapStart = Addr_MIN;
3390cb249ab3febb3757a0b0582be21952efacf415e5sewardj   while (True) {
3391cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (i >= buf_n_tot) break;
3392cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3393cb249ab3febb3757a0b0582be21952efacf415e5sewardj      /* Read (without fscanf :) the pattern %16x-%16x %c%c%c%c %16x %2x:%2x %d */
3394cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readhex(&procmap_buf[i], &start);
3395cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j > 0) i += j; else goto syntaxerror;
3396cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ch);
3397cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && ch == '-') i += j; else goto syntaxerror;
3398cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readhex(&procmap_buf[i], &endPlusOne);
3399cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j > 0) i += j; else goto syntaxerror;
3400cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3401cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ch);
3402cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && ch == ' ') i += j; else goto syntaxerror;
3403cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3404cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &rr);
3405cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && (rr == 'r' || rr == '-')) i += j; else goto syntaxerror;
3406cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ww);
3407cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && (ww == 'w' || ww == '-')) i += j; else goto syntaxerror;
3408cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &xx);
3409cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && (xx == 'x' || xx == '-')) i += j; else goto syntaxerror;
3410cb249ab3febb3757a0b0582be21952efacf415e5sewardj      /* This field is the shared/private flag */
3411cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &pp);
3412cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && (pp == 'p' || pp == '-' || pp == 's'))
3413cb249ab3febb3757a0b0582be21952efacf415e5sewardj                                              i += j; else goto syntaxerror;
3414cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3415cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ch);
3416cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && ch == ' ') i += j; else goto syntaxerror;
3417cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3418274461dcb67f680196c97e8afb7028a79b97dcb7sewardj      j = readhex64(&procmap_buf[i], &foffset);
3419cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j > 0) i += j; else goto syntaxerror;
3420cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3421cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ch);
3422cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && ch == ' ') i += j; else goto syntaxerror;
3423cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3424cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readhex(&procmap_buf[i], &maj);
3425cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j > 0) i += j; else goto syntaxerror;
3426cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ch);
3427cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && ch == ':') i += j; else goto syntaxerror;
3428cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readhex(&procmap_buf[i], &min);
3429cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j > 0) i += j; else goto syntaxerror;
3430cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3431cb249ab3febb3757a0b0582be21952efacf415e5sewardj      j = readchar(&procmap_buf[i], &ch);
3432cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j == 1 && ch == ' ') i += j; else goto syntaxerror;
3433cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3434419060073e7943846cc9e0bcdcb25258d90da2dcsewardj      j = readdec64(&procmap_buf[i], &ino);
3435cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (j > 0) i += j; else goto syntaxerror;
3436cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3437cb249ab3febb3757a0b0582be21952efacf415e5sewardj      goto read_line_ok;
3438cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3439cb249ab3febb3757a0b0582be21952efacf415e5sewardj    syntaxerror:
3440cb249ab3febb3757a0b0582be21952efacf415e5sewardj      VG_(debugLog)(0, "Valgrind:",
3441cb249ab3febb3757a0b0582be21952efacf415e5sewardj                       "FATAL: syntax error reading /proc/self/maps\n");
3442cb249ab3febb3757a0b0582be21952efacf415e5sewardj      { Int k, m;
3443cb249ab3febb3757a0b0582be21952efacf415e5sewardj        HChar buf50[51];
3444cb249ab3febb3757a0b0582be21952efacf415e5sewardj        m = 0;
3445cb249ab3febb3757a0b0582be21952efacf415e5sewardj        buf50[m] = 0;
3446cb249ab3febb3757a0b0582be21952efacf415e5sewardj        k = i - 50;
3447cb249ab3febb3757a0b0582be21952efacf415e5sewardj        if (k < 0) k = 0;
3448cb249ab3febb3757a0b0582be21952efacf415e5sewardj        for (; k <= i; k++) {
3449cb249ab3febb3757a0b0582be21952efacf415e5sewardj           buf50[m] = procmap_buf[k];
3450cb249ab3febb3757a0b0582be21952efacf415e5sewardj           buf50[m+1] = 0;
3451cb249ab3febb3757a0b0582be21952efacf415e5sewardj           if (m < 50-1) m++;
3452cb249ab3febb3757a0b0582be21952efacf415e5sewardj        }
3453cb249ab3febb3757a0b0582be21952efacf415e5sewardj        VG_(debugLog)(0, "procselfmaps", "Last 50 chars: '%s'\n", buf50);
3454cb249ab3febb3757a0b0582be21952efacf415e5sewardj      }
3455297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj      ML_(am_exit)(1);
3456cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3457cb249ab3febb3757a0b0582be21952efacf415e5sewardj    read_line_ok:
3458cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3459bd28c5e5dbdf69de901c025f67d4c1af24175492florian      aspacem_assert(i < buf_n_tot);
3460bd28c5e5dbdf69de901c025f67d4c1af24175492florian
3461cb249ab3febb3757a0b0582be21952efacf415e5sewardj      /* Try and find the name of the file mapped to this segment, if
3462bd28c5e5dbdf69de901c025f67d4c1af24175492florian         it exists.  Note that file names can contain spaces. */
3463cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3464bd28c5e5dbdf69de901c025f67d4c1af24175492florian      // Move i to the next non-space char, which should be either a '/',
3465bd28c5e5dbdf69de901c025f67d4c1af24175492florian      // a '[', or a newline.
3466bd28c5e5dbdf69de901c025f67d4c1af24175492florian      while (procmap_buf[i] == ' ') i++;
3467cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3468cb249ab3febb3757a0b0582be21952efacf415e5sewardj      // Move i_eol to the end of the line.
3469cb249ab3febb3757a0b0582be21952efacf415e5sewardj      i_eol = i;
3470bd28c5e5dbdf69de901c025f67d4c1af24175492florian      while (procmap_buf[i_eol] != '\n') i_eol++;
3471cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3472cb249ab3febb3757a0b0582be21952efacf415e5sewardj      // If there's a filename...
3473bd28c5e5dbdf69de901c025f67d4c1af24175492florian      if (procmap_buf[i] == '/') {
3474cb249ab3febb3757a0b0582be21952efacf415e5sewardj         /* Minor hack: put a '\0' at the filename end for the call to
3475cb249ab3febb3757a0b0582be21952efacf415e5sewardj            'record_mapping', then restore the old char with 'tmp'. */
3476cb249ab3febb3757a0b0582be21952efacf415e5sewardj         filename = &procmap_buf[i];
3477cb249ab3febb3757a0b0582be21952efacf415e5sewardj         tmp = filename[i_eol - i];
3478cb249ab3febb3757a0b0582be21952efacf415e5sewardj         filename[i_eol - i] = '\0';
3479cb249ab3febb3757a0b0582be21952efacf415e5sewardj      } else {
3480cb249ab3febb3757a0b0582be21952efacf415e5sewardj	 tmp = 0;
3481cb249ab3febb3757a0b0582be21952efacf415e5sewardj         filename = NULL;
3482cb249ab3febb3757a0b0582be21952efacf415e5sewardj         foffset = 0;
3483cb249ab3febb3757a0b0582be21952efacf415e5sewardj      }
3484cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3485cb249ab3febb3757a0b0582be21952efacf415e5sewardj      prot = 0;
3486cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (rr == 'r') prot |= VKI_PROT_READ;
3487cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (ww == 'w') prot |= VKI_PROT_WRITE;
3488cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (xx == 'x') prot |= VKI_PROT_EXEC;
3489cb249ab3febb3757a0b0582be21952efacf415e5sewardj
349099ffec4b2a139513c77a420a459d5ea9beaadb98tom      /* Linux has two ways to encode a device number when it
349199ffec4b2a139513c77a420a459d5ea9beaadb98tom         is exposed to user space (via fstat etc). The old way
349299ffec4b2a139513c77a420a459d5ea9beaadb98tom         is the traditional unix scheme that produces a 16 bit
349399ffec4b2a139513c77a420a459d5ea9beaadb98tom         device number with the top 8 being the major number and
349499ffec4b2a139513c77a420a459d5ea9beaadb98tom         the bottom 8 the minor number.
349599ffec4b2a139513c77a420a459d5ea9beaadb98tom
349699ffec4b2a139513c77a420a459d5ea9beaadb98tom         The new scheme allows for a 12 bit major number and
349799ffec4b2a139513c77a420a459d5ea9beaadb98tom         a 20 bit minor number by using a 32 bit device number
349899ffec4b2a139513c77a420a459d5ea9beaadb98tom         and putting the top 12 bits of the minor number into
349999ffec4b2a139513c77a420a459d5ea9beaadb98tom         the top 12 bits of the device number thus leaving an
350099ffec4b2a139513c77a420a459d5ea9beaadb98tom         extra 4 bits for the major number.
350199ffec4b2a139513c77a420a459d5ea9beaadb98tom
350299ffec4b2a139513c77a420a459d5ea9beaadb98tom         If the minor and major number are both single byte
350399ffec4b2a139513c77a420a459d5ea9beaadb98tom         values then both schemes give the same result so we
350499ffec4b2a139513c77a420a459d5ea9beaadb98tom         use the new scheme here in case either number is
350599ffec4b2a139513c77a420a459d5ea9beaadb98tom         outside the 0-255 range and then use fstat64 when
350699ffec4b2a139513c77a420a459d5ea9beaadb98tom         available (or fstat on 64 bit systems) so that we
350799ffec4b2a139513c77a420a459d5ea9beaadb98tom         should always have a new style device number and
350899ffec4b2a139513c77a420a459d5ea9beaadb98tom         everything should match. */
350999ffec4b2a139513c77a420a459d5ea9beaadb98tom      dev = (min & 0xff) | (maj << 8) | ((min & ~0xff) << 12);
351099ffec4b2a139513c77a420a459d5ea9beaadb98tom
3511cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if (record_gap && gapStart < start)
3512cb249ab3febb3757a0b0582be21952efacf415e5sewardj         (*record_gap) ( gapStart, start-gapStart );
3513cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3514e6bbc36e0095970ded2564c1763026c79ccadbdesewardj      if (record_mapping && start < endPlusOne)
3515e6bbc36e0095970ded2564c1763026c79ccadbdesewardj         (*record_mapping) ( start, endPlusOne-start,
3516e6bbc36e0095970ded2564c1763026c79ccadbdesewardj                             prot, dev, ino,
3517e6bbc36e0095970ded2564c1763026c79ccadbdesewardj                             foffset, filename );
3518cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3519cb249ab3febb3757a0b0582be21952efacf415e5sewardj      if ('\0' != tmp) {
3520cb249ab3febb3757a0b0582be21952efacf415e5sewardj         filename[i_eol - i] = tmp;
3521cb249ab3febb3757a0b0582be21952efacf415e5sewardj      }
3522cb249ab3febb3757a0b0582be21952efacf415e5sewardj
3523cb249ab3febb3757a0b0582be21952efacf415e5sewardj      i = i_eol + 1;
3524cb249ab3febb3757a0b0582be21952efacf415e5sewardj      gapStart = endPlusOne;
3525cb249ab3febb3757a0b0582be21952efacf415e5sewardj   }
3526cb249ab3febb3757a0b0582be21952efacf415e5sewardj
352738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  if defined(VGP_arm_linux)
352838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   /* ARM puts code at the end of memory that contains processor
352938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      specific stuff (cmpxchg, getting the thread local storage, etc.)
353038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      This isn't specified in /proc/self/maps, so do it here.  This
353138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      kludgery causes the view of memory, as presented to
353238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      record_gap/record_mapping, to actually reflect reality.  IMO
353338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      (JRS, 2010-Jan-03) the fact that /proc/.../maps does not list
353438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj      the commpage should be regarded as a bug in the kernel. */
353538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   { const Addr commpage_start = ARM_LINUX_FAKE_COMMPAGE_START;
353638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj     const Addr commpage_end1  = ARM_LINUX_FAKE_COMMPAGE_END1;
353738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj     if (gapStart < commpage_start) {
353838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj        if (record_gap)
353938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj           (*record_gap)( gapStart, commpage_start - gapStart );
354038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj        if (record_mapping)
354138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj           (*record_mapping)( commpage_start, commpage_end1 - commpage_start,
354238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj                              VKI_PROT_READ|VKI_PROT_EXEC,
354338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj                              0/*dev*/, 0/*ino*/, 0/*foffset*/,
354438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj                              NULL);
354538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj        gapStart = commpage_end1;
354638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj     }
354738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj   }
354838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#  endif
354938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
3550cb249ab3febb3757a0b0582be21952efacf415e5sewardj   if (record_gap && gapStart < Addr_MAX)
3551cb249ab3febb3757a0b0582be21952efacf415e5sewardj      (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 );
3552cb249ab3febb3757a0b0582be21952efacf415e5sewardj}
3553cb249ab3febb3757a0b0582be21952efacf415e5sewardj
355438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------END-procmaps-parser-for-Linux----------------------------*/
355538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
355638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------BEGIN-procmaps-parser-for-Darwin-------------------------*/
355738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj
3558f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin)
3559f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach/mach.h>
3560f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach/mach_vm.h>
3561f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3562f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic unsigned int mach2vki(unsigned int vm_prot)
3563f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
3564f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   return
3565f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ((vm_prot & VM_PROT_READ)    ? VKI_PROT_READ    : 0) |
3566f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ((vm_prot & VM_PROT_WRITE)   ? VKI_PROT_WRITE   : 0) |
3567f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      ((vm_prot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC    : 0) ;
3568f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
3569f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3570f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic UInt stats_machcalls = 0;
3571f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3572f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void parse_procselfmaps (
3573f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      void (*record_mapping)( Addr addr, SizeT len, UInt prot,
3574f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                              ULong dev, ULong ino, Off64T offset,
3575dbb3584f591710a15a437918c0fc27e300993566florian                              const HChar* filename ),
3576f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      void (*record_gap)( Addr addr, SizeT len )
3577f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   )
3578f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
3579f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vm_address_t iter;
3580f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   unsigned int depth;
3581f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   vm_address_t last;
3582f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3583f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   iter = 0;
3584f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   depth = 0;
3585f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   last = 0;
3586f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   while (1) {
3587f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      mach_vm_address_t addr = iter;
3588f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      mach_vm_size_t size;
3589f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      vm_region_submap_short_info_data_64_t info;
3590f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      kern_return_t kr;
3591f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3592f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      while (1) {
3593f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         mach_msg_type_number_t info_count
3594f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
3595f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         stats_machcalls++;
3596f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         kr = mach_vm_region_recurse(mach_task_self(), &addr, &size, &depth,
3597f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                                     (vm_region_info_t)&info, &info_count);
3598f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (kr)
3599f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            return;
3600f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (info.is_submap) {
3601f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            depth++;
3602f76d27a697a7b0bf3b84490baf60623fc96a23afnjn            continue;
3603f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
3604f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         break;
3605f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
3606f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      iter = addr + size;
3607f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3608f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (addr > last  &&  record_gap) {
3609f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         (*record_gap)(last, addr - last);
3610f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
3611f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (record_mapping) {
3612f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         (*record_mapping)(addr, size, mach2vki(info.protection),
3613f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                           0, 0, info.offset, NULL);
3614f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
3615f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      last = addr + size;
3616f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
3617f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3618f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if ((Addr)-1 > last  &&  record_gap)
3619f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      (*record_gap)(last, (Addr)-1 - last);
3620f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
3621f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
36229edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardj// Urr.  So much for thread safety.
36239edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic Bool        css_overflowed;
36249edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic ChangedSeg* css_local;
36259edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic Int         css_size_local;
36269edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic Int         css_used_local;
3627f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3628e139a46c2961c48392005fb367ef6380ea57df4bsewardjstatic Addr Addr__max ( Addr a, Addr b ) { return a > b ? a : b; }
3629e139a46c2961c48392005fb367ef6380ea57df4bsewardjstatic Addr Addr__min ( Addr a, Addr b ) { return a < b ? a : b; }
3630e139a46c2961c48392005fb367ef6380ea57df4bsewardj
3631f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void add_mapping_callback(Addr addr, SizeT len, UInt prot,
3632f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                                 ULong dev, ULong ino, Off64T offset,
3633dbb3584f591710a15a437918c0fc27e300993566florian                                 const HChar *filename)
3634f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
3635f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // derived from sync_check_mapping_callback()
3636f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3637e139a46c2961c48392005fb367ef6380ea57df4bsewardj   /* JRS 2012-Mar-07: this all seems very dubious to me.  It would be
3638e139a46c2961c48392005fb367ef6380ea57df4bsewardj      safer to see if we can find, in V's segment collection, one
3639e139a46c2961c48392005fb367ef6380ea57df4bsewardj      single segment that completely covers the range [addr, +len)
3640e139a46c2961c48392005fb367ef6380ea57df4bsewardj      (and possibly more), and that has the exact same other
3641e139a46c2961c48392005fb367ef6380ea57df4bsewardj      properties (prot, dev, ino, offset, etc) as the data presented
3642e139a46c2961c48392005fb367ef6380ea57df4bsewardj      here.  If found, we just skip.  Otherwise add the data presented
3643e139a46c2961c48392005fb367ef6380ea57df4bsewardj      here into css_local[]. */
3644e139a46c2961c48392005fb367ef6380ea57df4bsewardj
3645f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Int iLo, iHi, i;
3646f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3647f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (len == 0) return;
3648f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3649f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* The kernel should not give us wraparounds. */
3650f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_assert(addr <= addr + len - 1);
3651f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3652f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   iLo = find_nsegment_idx( addr );
3653f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   iHi = find_nsegment_idx( addr + len - 1 );
3654f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3655f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* NSegments iLo .. iHi inclusive should agree with the presented
3656f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      data. */
3657f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   for (i = iLo; i <= iHi; i++) {
3658f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3659f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      UInt seg_prot;
3660f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3661f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      if (nsegments[i].kind == SkAnonV  ||  nsegments[i].kind == SkFileV) {
3662f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         /* Ignore V regions */
3663f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         continue;
3664f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
3665f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      else if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn) {
3666e139a46c2961c48392005fb367ef6380ea57df4bsewardj         /* Add mapping for SkResvn regions */
3667f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         ChangedSeg* cs = &css_local[css_used_local];
3668fd1b461d19d0fd0484682a51138308413a3eab0cnjn         if (css_used_local < css_size_local) {
3669fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->is_added = True;
3670fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->start    = addr;
3671fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->end      = addr + len - 1;
3672fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->prot     = prot;
3673fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->offset   = offset;
3674fd1b461d19d0fd0484682a51138308413a3eab0cnjn            css_used_local++;
3675fd1b461d19d0fd0484682a51138308413a3eab0cnjn         } else {
3676fd1b461d19d0fd0484682a51138308413a3eab0cnjn            css_overflowed = True;
3677fd1b461d19d0fd0484682a51138308413a3eab0cnjn         }
3678f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         return;
3679f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3680f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj      }
3681f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj      else if (nsegments[i].kind == SkAnonC ||
3682f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               nsegments[i].kind == SkFileC ||
3683f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               nsegments[i].kind == SkShmC)
3684f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      {
3685f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         /* Check permissions on client regions */
3686f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         // GrP fixme
3687f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         seg_prot = 0;
3688f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ;
3689f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (nsegments[i].hasW) seg_prot |= VKI_PROT_WRITE;
3690f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#        if defined(VGA_x86)
3691f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         // GrP fixme sloppyXcheck
3692f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         // darwin: kernel X ignored and spuriously changes? (vm_copy)
3693f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         seg_prot |= (prot & VKI_PROT_EXEC);
3694f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#        else
3695f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (nsegments[i].hasX) seg_prot |= VKI_PROT_EXEC;
3696f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#        endif
3697f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         if (seg_prot != prot) {
3698f76d27a697a7b0bf3b84490baf60623fc96a23afnjn             if (VG_(clo_trace_syscalls))
369908a631925b44574c66af84dc7ffd9f50976a5fdfsewardj                 VG_(debugLog)(0,"aspacem","region %p..%p permission "
370008a631925b44574c66af84dc7ffd9f50976a5fdfsewardj                                 "mismatch (kernel %x, V %x)\n",
3701f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                                 (void*)nsegments[i].start,
3702f76d27a697a7b0bf3b84490baf60623fc96a23afnjn                                 (void*)(nsegments[i].end+1), prot, seg_prot);
3703f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj            /* Add mapping for regions with protection changes */
3704f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj            ChangedSeg* cs = &css_local[css_used_local];
3705f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj            if (css_used_local < css_size_local) {
3706f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               cs->is_added = True;
3707f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               cs->start    = addr;
3708f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               cs->end      = addr + len - 1;
3709f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               cs->prot     = prot;
3710f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               cs->offset   = offset;
3711f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               css_used_local++;
3712f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj            } else {
3713f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj               css_overflowed = True;
3714f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj            }
3715f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj	    return;
3716f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj
3717f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         }
3718f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3719f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      } else {
3720f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         aspacem_assert(0);
3721f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
3722f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
3723f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
3724f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3725f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void remove_mapping_callback(Addr addr, SizeT len)
3726f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
3727f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // derived from sync_check_gap_callback()
3728f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3729f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   Int iLo, iHi, i;
3730f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3731f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (len == 0)
3732f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      return;
3733f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3734f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* The kernel should not give us wraparounds. */
3735f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_assert(addr <= addr + len - 1);
3736f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3737f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   iLo = find_nsegment_idx( addr );
3738f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   iHi = find_nsegment_idx( addr + len - 1 );
3739f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3740f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   /* NSegments iLo .. iHi inclusive should agree with the presented data. */
3741f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   for (i = iLo; i <= iHi; i++) {
3742e139a46c2961c48392005fb367ef6380ea57df4bsewardj      if (nsegments[i].kind != SkFree && nsegments[i].kind != SkResvn) {
3743e139a46c2961c48392005fb367ef6380ea57df4bsewardj         /* V has a mapping, kernel doesn't.  Add to css_local[],
3744e139a46c2961c48392005fb367ef6380ea57df4bsewardj            directives to chop off the part of the V mapping that
3745e139a46c2961c48392005fb367ef6380ea57df4bsewardj            falls within the gap that the kernel tells us is
3746e139a46c2961c48392005fb367ef6380ea57df4bsewardj            present. */
3747f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         ChangedSeg* cs = &css_local[css_used_local];
3748fd1b461d19d0fd0484682a51138308413a3eab0cnjn         if (css_used_local < css_size_local) {
3749fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->is_added = False;
3750e139a46c2961c48392005fb367ef6380ea57df4bsewardj            cs->start    = Addr__max(nsegments[i].start, addr);
3751e139a46c2961c48392005fb367ef6380ea57df4bsewardj            cs->end      = Addr__min(nsegments[i].end,   addr + len - 1);
3752e139a46c2961c48392005fb367ef6380ea57df4bsewardj            aspacem_assert(VG_IS_PAGE_ALIGNED(cs->start));
3753e139a46c2961c48392005fb367ef6380ea57df4bsewardj            aspacem_assert(VG_IS_PAGE_ALIGNED(cs->end+1));
3754e139a46c2961c48392005fb367ef6380ea57df4bsewardj            /* I don't think the following should fail.  But if it
3755e139a46c2961c48392005fb367ef6380ea57df4bsewardj               does, just omit the css_used_local++ in the cases where
3756e139a46c2961c48392005fb367ef6380ea57df4bsewardj               it doesn't hold. */
3757e139a46c2961c48392005fb367ef6380ea57df4bsewardj            aspacem_assert(cs->start < cs->end);
3758fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->prot     = 0;
3759fd1b461d19d0fd0484682a51138308413a3eab0cnjn            cs->offset   = 0;
3760fd1b461d19d0fd0484682a51138308413a3eab0cnjn            css_used_local++;
3761fd1b461d19d0fd0484682a51138308413a3eab0cnjn         } else {
3762fd1b461d19d0fd0484682a51138308413a3eab0cnjn            css_overflowed = True;
3763fd1b461d19d0fd0484682a51138308413a3eab0cnjn         }
3764f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      }
3765f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   }
3766f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
3767f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3768f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3769fd1b461d19d0fd0484682a51138308413a3eab0cnjn// Returns False if 'css' wasn't big enough.
3770fd1b461d19d0fd0484682a51138308413a3eab0cnjnBool VG_(get_changed_segments)(
3771f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css,
3772f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      Int css_size, /*OUT*/Int* css_used)
3773f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{
3774f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   static UInt stats_synccalls = 1;
3775f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   aspacem_assert(when && where);
3776f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3777f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   if (0)
3778f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      VG_(debugLog)(0,"aspacem",
3779f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         "[%u,%u] VG_(get_changed_segments)(%s, %s)\n",
3780f76d27a697a7b0bf3b84490baf60623fc96a23afnjn         stats_synccalls++, stats_machcalls, when, where
3781f76d27a697a7b0bf3b84490baf60623fc96a23afnjn      );
3782f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3783fd1b461d19d0fd0484682a51138308413a3eab0cnjn   css_overflowed = False;
3784f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   css_local = css;
3785f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   css_size_local = css_size;
3786f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   css_used_local = 0;
3787f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3788f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   // Get the list of segs that need to be added/removed.
3789f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   parse_procselfmaps(&add_mapping_callback, &remove_mapping_callback);
3790f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
3791f76d27a697a7b0bf3b84490baf60623fc96a23afnjn   *css_used = css_used_local;
3792fd1b461d19d0fd0484682a51138308413a3eab0cnjn
3793fd1b461d19d0fd0484682a51138308413a3eab0cnjn   if (css_overflowed) {
3794fd1b461d19d0fd0484682a51138308413a3eab0cnjn      aspacem_assert(css_used_local == css_size_local);
3795fd1b461d19d0fd0484682a51138308413a3eab0cnjn   }
3796fd1b461d19d0fd0484682a51138308413a3eab0cnjn
3797fd1b461d19d0fd0484682a51138308413a3eab0cnjn   return !css_overflowed;
3798f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}
3799f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
380038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#endif // defined(VGO_darwin)
3801c401ae7ea8e709040d70a2ea6e2e44979aa90ac0bart
380238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------END-procmaps-parser-for-Darwin---------------------------*/
38038b68b64759254d514d98328c496cbd88cde4c9a5njn
38048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*------BEGIN-procmaps-parser-for-Solaris------------------------*/
38058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris)
38078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Note: /proc/self/xmap contains extended information about already
38098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   materialized mappings whereas /proc/self/rmap contains information about
38108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   all mappings including reserved but yet-to-materialize mappings (mmap'ed
38118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   with MAP_NORESERVE flag, such as thread stacks). But /proc/self/rmap does
38128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   not contain extended information found in /proc/self/xmap. Therefore
38138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   information from both sources need to be combined.
38148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */
38158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38168eb8bab992e3998c33770b0cdb16059a8b918a06sewardjtypedef struct
38178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
38188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr   addr;
38198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT  size;
38208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   UInt   prot;
38218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ULong  dev;
38228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ULong  ino;
38238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Off64T foffset;
38248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   HChar  filename[VKI_PATH_MAX];
38258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} Mapping;
38268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38278eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic SizeT read_proc_file(const HChar *filename, HChar *buf,
38288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                            SizeT buf_size, const HChar *buf_size_name,
38298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                            SizeT entry_size)
38308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
38318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SysRes res = ML_(am_open)(filename, VKI_O_RDONLY, 0);
38328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (sr_isError(res)) {
38338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      HChar message[100];
38348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_sprintf)(message, "Cannot open %s.", filename);
38358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_barf)(message);
38368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
38378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int fd = sr_Res(res);
38388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Int r = ML_(am_read)(fd, buf, buf_size);
38408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   ML_(am_close)(fd);
38418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (r < 0) {
38428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      HChar message[100];
38438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_sprintf)(message, "I/O error on %s.", filename);
38448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_barf)(message);
38458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
38468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (r >= buf_size)
38488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_barf_toolow)(buf_size_name);
38498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (r % entry_size != 0) {
38518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      HChar message[100];
38528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_sprintf)(message, "Bogus values read from %s.", filename);
38538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_barf)(message);
38548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
38558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return r / entry_size;
38578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
38588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38598eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic Mapping *next_xmap(const HChar *buffer, SizeT entries, SizeT *idx,
38608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                          Mapping *mapping)
38618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
38628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(idx);
38638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(mapping);
38648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (*idx >= entries)
38668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      return NULL; /* No more entries */
38678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   const vki_prxmap_t *map = (const vki_prxmap_t *)buffer + *idx;
38698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->addr = map->pr_vaddr;
38718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->size = map->pr_size;
38728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->prot = 0;
38748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mflags & VKI_MA_READ)
38758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->prot |= VKI_PROT_READ;
38768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mflags & VKI_MA_WRITE)
38778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->prot |= VKI_PROT_WRITE;
38788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mflags & VKI_MA_EXEC)
38798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->prot |= VKI_PROT_EXEC;
38808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_dev != VKI_PRNODEV) {
38828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->dev = map->pr_dev;
38838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->ino = map->pr_ino;
38848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->foffset = map->pr_offset;
38858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
38868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   else {
38878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->dev = 0;
38888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->ino = 0;
38898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->foffset = 0;
38908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
38918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
38928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Try to get the filename. */
38938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->filename[0] = '\0';
38948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mapname[0] != '\0') {
38958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      ML_(am_sprintf)(mapping->filename, "/proc/self/path/%s",
38968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                      map->pr_mapname);
38978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      Int r = ML_(am_readlink)(mapping->filename, mapping->filename,
38988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               sizeof(mapping->filename) - 1);
38998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (r == -1) {
39008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* If Valgrind is executed in a non-global zone and the link in
39018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            /proc/self/path/ represents a file that is available through lofs
39028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            from a global zone then the kernel may not be able to resolve the
39038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            link.
39048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            In such a case, return a corresponding /proc/self/object/ file to
39068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            allow Valgrind to read the file if it is necessary.
39078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            This can create some discrepancy for the sanity check. For
39098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            instance, if a client program mmaps some file then the address
39108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            space manager will have a correct zone-local name of that file,
39118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            but the sanity check will receive a different file name from this
39128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            code. This currently does not represent a problem because the
39138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            sanity check ignores the file names (it uses device and inode
39148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            numbers for the comparison).
39158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj          */
39168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         ML_(am_sprintf)(mapping->filename, "/proc/self/object/%s",
39178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                         map->pr_mapname);
39188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
39198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      else {
39208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         aspacem_assert(r >= 0);
39218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         mapping->filename[r] = '\0';
39228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
39238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
39248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *idx += 1;
39268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return mapping;
39278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
39288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39298eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic Mapping *next_rmap(const HChar *buffer, SizeT entries, SizeT *idx,
39308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                          Mapping *mapping)
39318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
39328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(idx);
39338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   aspacem_assert(mapping);
39348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (*idx >= entries)
39368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      return NULL; /* No more entries */
39378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   const vki_prmap_t *map = (const vki_prmap_t *)buffer + *idx;
39398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->addr = map->pr_vaddr;
39418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->size = map->pr_size;
39428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->prot = 0;
39448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mflags & VKI_MA_READ)
39458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->prot |= VKI_PROT_READ;
39468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mflags & VKI_MA_WRITE)
39478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->prot |= VKI_PROT_WRITE;
39488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (map->pr_mflags & VKI_MA_EXEC)
39498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      mapping->prot |= VKI_PROT_EXEC;
39508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->dev = 0;
39528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->ino = 0;
39538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->foffset = 0;
39548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   mapping->filename[0] = '\0';
39558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   *idx += 1;
39578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   return mapping;
39588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
39598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Used for two purposes:
39618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   1. Establish initial mappings upon the process startup
39628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   2. Check mappings during aspacemgr sanity check
39638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */
39648eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic void parse_procselfmaps (
39658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      void (*record_mapping)( Addr addr, SizeT len, UInt prot,
39668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                              ULong dev, ULong ino, Off64T offset,
39678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                              const HChar *filename ),
39688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      void (*record_gap)( Addr addr, SizeT len )
39698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   )
39708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{
39718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr start = Addr_MIN;
39728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Addr gap_start = Addr_MIN;
39738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#define M_XMAP_BUF (VG_N_SEGMENTS * sizeof(vki_prxmap_t))
39758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Static to keep it out of stack frame... */
39768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   static HChar xmap_buf[M_XMAP_BUF];
39778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   const Mapping *xmap = NULL;
39788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT xmap_index = 0; /* Current entry */
39798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT xmap_entries;
39808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Mapping xmap_mapping;
39818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Bool advance_xmap;
39828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#define M_RMAP_BUF (VG_N_SEGMENTS * sizeof(vki_prmap_t))
39848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   static HChar rmap_buf[M_RMAP_BUF];
39858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   const Mapping *rmap = NULL;
39868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT rmap_index = 0; /* Current entry */
39878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   SizeT rmap_entries;
39888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Mapping rmap_mapping;
39898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   Bool advance_rmap;
39908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Read fully /proc/self/xmap and /proc/self/rmap. */
39928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   xmap_entries = read_proc_file("/proc/self/xmap", xmap_buf, M_XMAP_BUF,
39938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                 "M_XMAP_BUF", sizeof(vki_prxmap_t));
39948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   rmap_entries = read_proc_file("/proc/self/rmap", rmap_buf, M_RMAP_BUF,
39968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                                 "M_RMAP_BUF", sizeof(vki_prmap_t));
39978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
39988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   /* Get the first xmap and rmap. */
39998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   advance_xmap = True;
40008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   advance_rmap = True;
40018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   while (1) {
40038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Get next xmap or rmap if necessary. */
40048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (advance_xmap) {
40058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         xmap = next_xmap(xmap_buf, xmap_entries, &xmap_index, &xmap_mapping);
40068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         advance_xmap = False;
40078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
40088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (advance_rmap) {
40098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         rmap = next_rmap(rmap_buf, rmap_entries, &rmap_index, &rmap_mapping);
40108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         advance_rmap = False;
40118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
40128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Check if the end has been reached. */
40148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (rmap == NULL)
40158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         break;
40168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      /* Invariants */
40188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (xmap != NULL) {
40198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         aspacem_assert(start <= xmap->addr);
40208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         aspacem_assert(rmap->addr <= xmap->addr);
40218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
40228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (xmap != NULL && start == xmap->addr) {
40248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* xmap mapping reached. */
40258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         aspacem_assert(xmap->addr >= rmap->addr &&
40268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                        xmap->addr + xmap->size <= rmap->addr + rmap->size);
40278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         aspacem_assert(xmap->prot == rmap->prot);
40288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         if (record_mapping != NULL)
40308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            (*record_mapping)(xmap->addr, xmap->size, xmap->prot, xmap->dev,
40318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                              xmap->ino, xmap->foffset,
40328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                              (xmap->filename[0] != '\0') ?
40338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj                               xmap->filename : NULL);
40348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         start = xmap->addr + xmap->size;
40368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         advance_xmap = True;
40378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
40388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      else if (start >= rmap->addr) {
40398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* Reserved-only part. */
40408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* First calculate size until the end of this reserved mapping... */
40418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         SizeT size = rmap->addr + rmap->size - start;
40428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* ... but shrink it if some xmap is in a way. */
40438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         if (xmap != NULL && size > xmap->addr - start)
40448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            size = xmap->addr - start;
40458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         if (record_mapping != NULL)
40478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            (*record_mapping)(start, size, rmap->prot, 0, 0, 0, NULL);
40488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         start += size;
40498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
40508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      else {
40518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         /* Gap. */
40528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         if (record_gap != NULL && gap_start < start)
40538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj            (*record_gap)(gap_start, start - gap_start);
40548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         start = rmap->addr;
40558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      }
40568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      if (rmap->addr + rmap->size <= start)
40588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj         advance_rmap = True;
40598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      gap_start = start;
40618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   }
40628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
40638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj   if (record_gap != NULL && gap_start < Addr_MAX)
40648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj      (*record_gap)(gap_start, Addr_MAX - gap_start + 1);
40658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj}
40668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
4067a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes/* parse_procselfmaps() callbacks do not allow for easy thread safety. */
4068a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic Addr found_addr;
4069a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic SizeT found_size;
4070a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic UInt found_prot;
4071a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
4072a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes/* Reports a new mapping into variables above. */
4073a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughesstatic void new_segment_found_callback(Addr addr, SizeT len, UInt prot,
4074a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   ULong dev, ULong ino, Off64T offset, const HChar *filename)
4075a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes{
4076a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   aspacem_assert(addr <= addr + len - 1);
4077a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
4078a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   Int iLo = find_nsegment_idx(addr);
4079a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   Int iHi = find_nsegment_idx(addr + len - 1);
4080a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   aspacem_assert(iLo <= iHi);
4081a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   aspacem_assert(nsegments[iLo].start <= addr);
4082a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   aspacem_assert(nsegments[iHi].end   >= addr + len - 1);
4083a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
4084a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   /* Do not perform any sanity checks. That is done in other places.
4085a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      Just find if a reported mapping is found in aspacemgr's book keeping. */
4086a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   for (Int i = iLo; i <= iHi; i++) {
4087a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      if ((nsegments[i].kind == SkFree) || (nsegments[i].kind == SkResvn)) {
4088a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         found_addr = addr;
4089a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         found_size = len;
4090a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         found_prot = prot;
4091a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes         break;
4092a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      }
4093a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   }
4094a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes}
4095a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
4096a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes/* Returns True if a new segment was found. */
4097a0664b9ca67b594bd6f570a61d3301167a24750cElliott HughesBool VG_(am_search_for_new_segment)(Addr *addr, SizeT *size, UInt *prot)
4098a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes{
4099a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   found_addr = 0;
4100a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   parse_procselfmaps(new_segment_found_callback, NULL);
4101a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
4102a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   if (found_addr != 0) {
4103a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      *addr = found_addr;
4104a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      *size = found_size;
4105a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      *prot = found_prot;
4106a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      return True;
4107a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   } else {
4108a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes      return False;
4109a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes   }
4110a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes}
4111a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes
41128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif // defined(VGO_solaris)
41138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
41148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*------END-procmaps-parser-for-Solaris--------------------------*/
41158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj
41168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
4117f76d27a697a7b0bf3b84490baf60623fc96a23afnjn
411898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge/*--------------------------------------------------------------------*/
4119945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--- end                                                          ---*/
4120de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
4121