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