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 14b3a1e4bffbdbbf38304f216af405009868f43628sewardj Copyright (C) 2000-2015 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 2634f3ef1ff3af3c637f38d4352f38581effba95c4esewardj enforce seperation 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 { \ 33845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 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 1085a364d119b3847143d804e388d7a37c2c82be93bfsewardj static UWord n_q = 0; 1086a364d119b3847143d804e388d7a37c2c82be93bfsewardj static UWord n_m = 0; 1087a364d119b3847143d804e388d7a37c2c82be93bfsewardj 1088a364d119b3847143d804e388d7a37c2c82be93bfsewardj UWord ix; 1089a364d119b3847143d804e388d7a37c2c82be93bfsewardj 1090a364d119b3847143d804e388d7a37c2c82be93bfsewardj if (LIKELY(cache_inited)) { 1091a364d119b3847143d804e388d7a37c2c82be93bfsewardj /* do nothing */ 1092a364d119b3847143d804e388d7a37c2c82be93bfsewardj } else { 1093a364d119b3847143d804e388d7a37c2c82be93bfsewardj for (ix = 0; ix < N_CACHE; ix++) { 1094a364d119b3847143d804e388d7a37c2c82be93bfsewardj cache_pageno[ix] = 0; 1095a364d119b3847143d804e388d7a37c2c82be93bfsewardj cache_segidx[ix] = -1; 1096a364d119b3847143d804e388d7a37c2c82be93bfsewardj } 1097a364d119b3847143d804e388d7a37c2c82be93bfsewardj cache_inited = True; 1098a364d119b3847143d804e388d7a37c2c82be93bfsewardj } 1099a364d119b3847143d804e388d7a37c2c82be93bfsewardj 1100a364d119b3847143d804e388d7a37c2c82be93bfsewardj ix = (a >> 12) % N_CACHE; 1101a364d119b3847143d804e388d7a37c2c82be93bfsewardj 1102a364d119b3847143d804e388d7a37c2c82be93bfsewardj n_q++; 1103a364d119b3847143d804e388d7a37c2c82be93bfsewardj if (0 && 0 == (n_q & 0xFFFF)) 1104a364d119b3847143d804e388d7a37c2c82be93bfsewardj VG_(debugLog)(0,"xxx","find_nsegment_idx: %lu %lu\n", n_q, n_m); 1105a364d119b3847143d804e388d7a37c2c82be93bfsewardj 1106a364d119b3847143d804e388d7a37c2c82be93bfsewardj if ((a >> 12) == cache_pageno[ix] 1107a364d119b3847143d804e388d7a37c2c82be93bfsewardj && cache_segidx[ix] >= 0 1108a364d119b3847143d804e388d7a37c2c82be93bfsewardj && cache_segidx[ix] < nsegments_used 1109a364d119b3847143d804e388d7a37c2c82be93bfsewardj && nsegments[cache_segidx[ix]].start <= a 1110a364d119b3847143d804e388d7a37c2c82be93bfsewardj && a <= nsegments[cache_segidx[ix]].end) { 1111a364d119b3847143d804e388d7a37c2c82be93bfsewardj /* hit */ 1112a364d119b3847143d804e388d7a37c2c82be93bfsewardj /* aspacem_assert( cache_segidx[ix] == find_nsegment_idx_WRK(a) ); */ 1113a364d119b3847143d804e388d7a37c2c82be93bfsewardj return cache_segidx[ix]; 1114a364d119b3847143d804e388d7a37c2c82be93bfsewardj } 1115a364d119b3847143d804e388d7a37c2c82be93bfsewardj /* miss */ 1116a364d119b3847143d804e388d7a37c2c82be93bfsewardj n_m++; 1117a364d119b3847143d804e388d7a37c2c82be93bfsewardj cache_segidx[ix] = find_nsegment_idx_WRK(a); 1118a364d119b3847143d804e388d7a37c2c82be93bfsewardj cache_pageno[ix] = a >> 12; 1119a364d119b3847143d804e388d7a37c2c82be93bfsewardj return cache_segidx[ix]; 1120a364d119b3847143d804e388d7a37c2c82be93bfsewardj# undef N_CACHE 1121a364d119b3847143d804e388d7a37c2c82be93bfsewardj} 1122a364d119b3847143d804e388d7a37c2c82be93bfsewardj 1123a364d119b3847143d804e388d7a37c2c82be93bfsewardj 11247cb1293f977ba78a06a63053e404493d545394edflorian/* Finds the segment containing 'a'. Only returns non-SkFree segments. */ 1125716f31ac50be6070a96b490d0b0bbd39b8e77342sewardjNSegment const * VG_(am_find_nsegment) ( Addr a ) 112645f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 112745f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i = find_nsegment_idx(a); 112845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(i >= 0 && i < nsegments_used); 112945f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments[i].start <= a); 113045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(a <= nsegments[i].end); 113145f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].kind == SkFree) 113245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return NULL; 113345f4e7c91119c7d01a59f5e827c67841632c9314sewardj else 113445f4e7c91119c7d01a59f5e827c67841632c9314sewardj return &nsegments[i]; 113545f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 113645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 11378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Finds an anonymous segment containing 'a'. Returned pointer is read only. */ 11388eb8bab992e3998c33770b0cdb16059a8b918a06sewardjNSegment const *VG_(am_find_anon_segment) ( Addr a ) 11398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 11408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Int i = find_nsegment_idx(a); 11418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(i >= 0 && i < nsegments_used); 11428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(nsegments[i].start <= a); 11438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(a <= nsegments[i].end); 11448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (nsegments[i].kind == SkAnonC || nsegments[i].kind == SkAnonV) 11458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return &nsegments[i]; 11468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj else 11478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return NULL; 11488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 114945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1150686b8cad58180b009f8df91509d0a5da2191167aflorian/* Map segment pointer to segment index. */ 11513e7986312a0ffc7646b0552d4c4ea3744a870e73florianstatic Int segAddr_to_index ( const NSegment* seg ) 115245f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 1153686b8cad58180b009f8df91509d0a5da2191167aflorian aspacem_assert(seg >= &nsegments[0] && seg < &nsegments[nsegments_used]); 1154686b8cad58180b009f8df91509d0a5da2191167aflorian 1155686b8cad58180b009f8df91509d0a5da2191167aflorian return seg - &nsegments[0]; 115645f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 115745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 115845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 11597cb1293f977ba78a06a63053e404493d545394edflorian/* Find the next segment along from 'here', if it is a non-SkFree segment. */ 11603e7986312a0ffc7646b0552d4c4ea3744a870e73florianNSegment const * VG_(am_next_nsegment) ( const NSegment* here, Bool fwds ) 116145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 116245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i = segAddr_to_index(here); 1163686b8cad58180b009f8df91509d0a5da2191167aflorian 116445f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (fwds) { 116545f4e7c91119c7d01a59f5e827c67841632c9314sewardj i++; 116645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (i >= nsegments_used) 116745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return NULL; 116845f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else { 116945f4e7c91119c7d01a59f5e827c67841632c9314sewardj i--; 117045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (i < 0) 117145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return NULL; 117245f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 11737cb1293f977ba78a06a63053e404493d545394edflorian if (nsegments[i].kind == SkFree) 11747cb1293f977ba78a06a63053e404493d545394edflorian return NULL; 11757cb1293f977ba78a06a63053e404493d545394edflorian else 11767cb1293f977ba78a06a63053e404493d545394edflorian return &nsegments[i]; 117745f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 117845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 117945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 118045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Trivial fn: return the total amount of space in anonymous mappings, 118145f4e7c91119c7d01a59f5e827c67841632c9314sewardj both for V and the client. Is used for printing stats in 118245f4e7c91119c7d01a59f5e827c67841632c9314sewardj out-of-memory messages. */ 118345f4e7c91119c7d01a59f5e827c67841632c9314sewardjULong VG_(am_get_anonsize_total)( void ) 118445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 118545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i; 118645f4e7c91119c7d01a59f5e827c67841632c9314sewardj ULong total = 0; 118745f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = 0; i < nsegments_used; i++) { 118845f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].kind == SkAnonC || nsegments[i].kind == SkAnonV) { 118945f4e7c91119c7d01a59f5e827c67841632c9314sewardj total += (ULong)nsegments[i].end 119045f4e7c91119c7d01a59f5e827c67841632c9314sewardj - (ULong)nsegments[i].start + 1ULL; 119145f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 119245f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 119345f4e7c91119c7d01a59f5e827c67841632c9314sewardj return total; 119445f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 119545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 119645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1197adfff76735ea5bca870dec8f382b225728e1b32dphilippe/* Test if a piece of memory is addressable by client or by valgrind with at 119845f4e7c91119c7d01a59f5e827c67841632c9314sewardj least the "prot" protection permissions by examining the underlying 1199a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian segments. The KINDS argument specifies the allowed segments ADDR may 1200a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian belong to in order to be considered "valid". 120145f4e7c91119c7d01a59f5e827c67841632c9314sewardj*/ 120245f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic 1203a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorianBool is_valid_for( UInt kinds, Addr start, SizeT len, UInt prot ) 120445f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 120545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i, iLo, iHi; 120645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool needR, needW, needX; 120745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 120845f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (len == 0) 120945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; /* somewhat dubious case */ 121045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (start + len < start) 121145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; /* reject wraparounds */ 121245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 121345f4e7c91119c7d01a59f5e827c67841632c9314sewardj needR = toBool(prot & VKI_PROT_READ); 121445f4e7c91119c7d01a59f5e827c67841632c9314sewardj needW = toBool(prot & VKI_PROT_WRITE); 121545f4e7c91119c7d01a59f5e827c67841632c9314sewardj needX = toBool(prot & VKI_PROT_EXEC); 121645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 121745f4e7c91119c7d01a59f5e827c67841632c9314sewardj iLo = find_nsegment_idx(start); 121845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(start >= nsegments[iLo].start); 121945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 122045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (start+len-1 <= nsegments[iLo].end) { 122145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* This is a speedup hack which avoids calling find_nsegment_idx 122245f4e7c91119c7d01a59f5e827c67841632c9314sewardj a second time when possible. It is always correct to just 122345f4e7c91119c7d01a59f5e827c67841632c9314sewardj use the "else" clause below, but is_valid_for_client is 122445f4e7c91119c7d01a59f5e827c67841632c9314sewardj called a lot by the leak checker, so avoiding pointless calls 122545f4e7c91119c7d01a59f5e827c67841632c9314sewardj to find_nsegment_idx, which can be expensive, is helpful. */ 122645f4e7c91119c7d01a59f5e827c67841632c9314sewardj iHi = iLo; 122745f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else { 122845f4e7c91119c7d01a59f5e827c67841632c9314sewardj iHi = find_nsegment_idx(start + len - 1); 122945f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 123045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1231a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian for (i = iLo; i <= iHi; i++) { 1232a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian if ( (nsegments[i].kind & kinds) != 0 1233a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian && (needR ? nsegments[i].hasR : True) 1234a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian && (needW ? nsegments[i].hasW : True) 1235a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian && (needX ? nsegments[i].hasX : True) ) { 1236a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian /* ok */ 1237a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian } else { 1238a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian return False; 123945f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 124045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 1241a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian 124245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; 124345f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 124445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 124545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Test if a piece of memory is addressable by the client with at 124645f4e7c91119c7d01a59f5e827c67841632c9314sewardj least the "prot" protection permissions by examining the underlying 124745f4e7c91119c7d01a59f5e827c67841632c9314sewardj segments. */ 124845f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_is_valid_for_client)( Addr start, SizeT len, 124945f4e7c91119c7d01a59f5e827c67841632c9314sewardj UInt prot ) 125045f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 1251a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian const UInt kinds = SkFileC | SkAnonC | SkShmC; 1252a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian 1253a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian return is_valid_for(kinds, start, len, prot); 125445f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 125545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 125645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Variant of VG_(am_is_valid_for_client) which allows free areas to 125745f4e7c91119c7d01a59f5e827c67841632c9314sewardj be consider part of the client's addressable space. It also 125845f4e7c91119c7d01a59f5e827c67841632c9314sewardj considers reservations to be allowable, since from the client's 125945f4e7c91119c7d01a59f5e827c67841632c9314sewardj point of view they don't exist. */ 126045f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_is_valid_for_client_or_free_or_resvn) 126145f4e7c91119c7d01a59f5e827c67841632c9314sewardj ( Addr start, SizeT len, UInt prot ) 126245f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 1263a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian const UInt kinds = SkFileC | SkAnonC | SkShmC | SkFree | SkResvn; 1264a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian 1265a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian return is_valid_for(kinds, start, len, prot); 126645f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 126745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1268e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr/* Checks if a piece of memory consists of either free or reservation 1269e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr segments. */ 1270e8b9ee37f8a49881dffd1900b5c397768f54a53biraisrBool VG_(am_is_free_or_resvn)( Addr start, SizeT len ) 1271e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr{ 1272e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr const UInt kinds = SkFree | SkResvn; 1273e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr 1274e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr return is_valid_for(kinds, start, len, 0); 1275e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr} 1276e8b9ee37f8a49881dffd1900b5c397768f54a53biraisr 127745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1278adfff76735ea5bca870dec8f382b225728e1b32dphilippeBool VG_(am_is_valid_for_valgrind) ( Addr start, SizeT len, UInt prot ) 127945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 1280a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian const UInt kinds = SkFileV | SkAnonV; 1281a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian 1282a623345e71045f9b4f130d2a9a22c1ad0c101b6fflorian return is_valid_for(kinds, start, len, prot); 128345f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 128445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 128545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 128645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Returns True if any part of the address range is marked as having 128745f4e7c91119c7d01a59f5e827c67841632c9314sewardj translations made from it. This is used to determine when to 128845f4e7c91119c7d01a59f5e827c67841632c9314sewardj discard code, so if in doubt return True. */ 128945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 129045f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic Bool any_Ts_in_range ( Addr start, SizeT len ) 129145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 129245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int iLo, iHi, i; 129345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(len > 0); 129445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(start + len > start); 129545f4e7c91119c7d01a59f5e827c67841632c9314sewardj iLo = find_nsegment_idx(start); 129645f4e7c91119c7d01a59f5e827c67841632c9314sewardj iHi = find_nsegment_idx(start + len - 1); 129745f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = iLo; i <= iHi; i++) { 129845f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].hasT) 129945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; 130045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 130145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 130245f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 130345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 130445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 13058f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian/* Check whether ADDR looks like an address or address-to-be located in an 13068f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian extensible client stack segment. Return true if 13078f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian (1) ADDR is located in an already mapped stack segment, OR 13088f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian (2) ADDR is located in a reservation segment into which an abutting SkAnonC 1309017d8f5410cff379575eee4f5056fb1a82a6526bflorian segment can be extended. */ 13108f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florianBool VG_(am_addr_is_in_extensible_client_stack)( Addr addr ) 1311017d8f5410cff379575eee4f5056fb1a82a6526bflorian{ 1312017d8f5410cff379575eee4f5056fb1a82a6526bflorian const NSegment *seg = nsegments + find_nsegment_idx(addr); 1313017d8f5410cff379575eee4f5056fb1a82a6526bflorian 1314017d8f5410cff379575eee4f5056fb1a82a6526bflorian switch (seg->kind) { 1315017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkFree: 1316017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkAnonV: 1317017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkFileV: 1318017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkFileC: 1319017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkShmC: 13208f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian return False; 1321017d8f5410cff379575eee4f5056fb1a82a6526bflorian 1322017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkResvn: { 13238f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian if (seg->smode != SmUpper) return False; 1324ad4e979f408239dabbaae955d8ffcb84a51a5c85florian /* If the abutting segment towards higher addresses is an SkAnonC 1325017d8f5410cff379575eee4f5056fb1a82a6526bflorian segment, then ADDR is a future stack pointer. */ 1326017d8f5410cff379575eee4f5056fb1a82a6526bflorian const NSegment *next = VG_(am_next_nsegment)(seg, /*forward*/ True); 13278f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian if (next == NULL || next->kind != SkAnonC) return False; 1328017d8f5410cff379575eee4f5056fb1a82a6526bflorian 1329017d8f5410cff379575eee4f5056fb1a82a6526bflorian /* OK; looks like a stack segment */ 13308f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian return True; 1331017d8f5410cff379575eee4f5056fb1a82a6526bflorian } 1332017d8f5410cff379575eee4f5056fb1a82a6526bflorian 1333017d8f5410cff379575eee4f5056fb1a82a6526bflorian case SkAnonC: { 1334017d8f5410cff379575eee4f5056fb1a82a6526bflorian /* If the abutting segment towards lower addresses is an SkResvn 1335017d8f5410cff379575eee4f5056fb1a82a6526bflorian segment, then ADDR is a stack pointer into mapped memory. */ 1336017d8f5410cff379575eee4f5056fb1a82a6526bflorian const NSegment *next = VG_(am_next_nsegment)(seg, /*forward*/ False); 1337d57686f198efb6fea6b0f5dd932bdf4f2299a96aflorian if (next == NULL || next->kind != SkResvn || next->smode != SmUpper) 13388f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian return False; 1339017d8f5410cff379575eee4f5056fb1a82a6526bflorian 1340017d8f5410cff379575eee4f5056fb1a82a6526bflorian /* OK; looks like a stack segment */ 13418f3cd17f6de44d563b7a3b2fdc5be9f0571bcdd8florian return True; 1342017d8f5410cff379575eee4f5056fb1a82a6526bflorian } 1343017d8f5410cff379575eee4f5056fb1a82a6526bflorian 1344017d8f5410cff379575eee4f5056fb1a82a6526bflorian default: 1345017d8f5410cff379575eee4f5056fb1a82a6526bflorian aspacem_assert(0); // should never happen 1346017d8f5410cff379575eee4f5056fb1a82a6526bflorian } 1347017d8f5410cff379575eee4f5056fb1a82a6526bflorian} 1348017d8f5410cff379575eee4f5056fb1a82a6526bflorian 134945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 135045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 135145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Modifying the segment array, and constructing segments. ---*/ 135245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 135345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 135445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 135545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Split the segment containing 'a' into two, so that 'a' is 135645f4e7c91119c7d01a59f5e827c67841632c9314sewardj guaranteed to be the start of a new segment. If 'a' is already the 135745f4e7c91119c7d01a59f5e827c67841632c9314sewardj start of a segment, do nothing. */ 135845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 135945f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void split_nsegment_at ( Addr a ) 136045f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 136145f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i, j; 136245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 136345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(a > 0); 136445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(a)); 136545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 136645f4e7c91119c7d01a59f5e827c67841632c9314sewardj i = find_nsegment_idx(a); 136745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(i >= 0 && i < nsegments_used); 136845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 136945f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].start == a) 137045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* 'a' is already the start point of a segment, so nothing to be 137145f4e7c91119c7d01a59f5e827c67841632c9314sewardj done. */ 137245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return; 137345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 137445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* else we have to slide the segments upwards to make a hole */ 137545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments_used >= VG_N_SEGMENTS) 1376297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ML_(am_barf_toolow)("VG_N_SEGMENTS"); 137745f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (j = nsegments_used-1; j > i; j--) 137845f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[j+1] = nsegments[j]; 137945f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments_used++; 138045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 138145f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i+1] = nsegments[i]; 138245f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i+1].start = a; 138345f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i].end = a-1; 138445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 138545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].kind == SkFileV || nsegments[i].kind == SkFileC) 138645f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i+1].offset 138745f4e7c91119c7d01a59f5e827c67841632c9314sewardj += ((ULong)nsegments[i+1].start) - ((ULong)nsegments[i].start); 138845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 13894ecd48360351f666f008148c12a24cbda455c6b1florian ML_(am_inc_refcount)(nsegments[i].fnIdx); 1390346ee2f7978bf2ab1ead4982e56870da276fc44bflorian 139145f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sane_NSegment(&nsegments[i])); 139245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sane_NSegment(&nsegments[i+1])); 139345f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 139445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 139545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 139645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Do the minimum amount of segment splitting necessary to ensure that 139745f4e7c91119c7d01a59f5e827c67841632c9314sewardj sLo is the first address denoted by some segment and sHi is the 139845f4e7c91119c7d01a59f5e827c67841632c9314sewardj highest address denoted by some other segment. Returns the indices 139945f4e7c91119c7d01a59f5e827c67841632c9314sewardj of the lowest and highest segments in the range. */ 140045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 140145f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic 140245f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid split_nsegments_lo_and_hi ( Addr sLo, Addr sHi, 140345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*OUT*/Int* iLo, 140445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*OUT*/Int* iHi ) 140545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 140645f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sLo < sHi); 140745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(sLo)); 140845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(sHi+1)); 140945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 141045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (sLo > 0) 141145f4e7c91119c7d01a59f5e827c67841632c9314sewardj split_nsegment_at(sLo); 141245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (sHi < sHi+1) 141345f4e7c91119c7d01a59f5e827c67841632c9314sewardj split_nsegment_at(sHi+1); 141445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 141545f4e7c91119c7d01a59f5e827c67841632c9314sewardj *iLo = find_nsegment_idx(sLo); 141645f4e7c91119c7d01a59f5e827c67841632c9314sewardj *iHi = find_nsegment_idx(sHi); 141745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(0 <= *iLo && *iLo < nsegments_used); 141845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(0 <= *iHi && *iHi < nsegments_used); 141945f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(*iLo <= *iHi); 142045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments[*iLo].start == sLo); 142145f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments[*iHi].end == sHi); 142245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Not that I'm overly paranoid or anything, definitely not :-) */ 142345f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 142445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 142545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 142645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Add SEG to the collection, deleting/truncating any it overlaps. 142745f4e7c91119c7d01a59f5e827c67841632c9314sewardj This deals with all the tricky cases of splitting up segments as 142845f4e7c91119c7d01a59f5e827c67841632c9314sewardj needed. */ 142945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 14303297124fa2116737066ac3cd709f18fdd5405163florianstatic void add_segment ( const NSegment* seg ) 143145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 143245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i, iLo, iHi, delta; 143345f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool segment_is_sane; 143445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 143545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr sStart = seg->start; 143645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr sEnd = seg->end; 143745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 143845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sStart <= sEnd); 143945f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(sStart)); 144045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(sEnd+1)); 144145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 144245f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment_is_sane = sane_NSegment(seg); 1443ddaef35bf689bb5192881aa6d455050e1423df7cnjn if (!segment_is_sane) show_nsegment_full(0,-1,seg); 144445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(segment_is_sane); 144545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 144645f4e7c91119c7d01a59f5e827c67841632c9314sewardj split_nsegments_lo_and_hi( sStart, sEnd, &iLo, &iHi ); 144745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 144845f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Now iLo .. iHi inclusive is the range of segment indices which 144945f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg will replace. If we're replacing more than one segment, 1450346ee2f7978bf2ab1ead4982e56870da276fc44bflorian slide those above the range down to fill the hole. Before doing 1451346ee2f7978bf2ab1ead4982e56870da276fc44bflorian that decrement the reference counters for the segments names of 1452346ee2f7978bf2ab1ead4982e56870da276fc44bflorian the replaced segments. */ 1453346ee2f7978bf2ab1ead4982e56870da276fc44bflorian for (i = iLo; i <= iHi; ++i) 14544ecd48360351f666f008148c12a24cbda455c6b1florian ML_(am_dec_refcount)(nsegments[i].fnIdx); 145545f4e7c91119c7d01a59f5e827c67841632c9314sewardj delta = iHi - iLo; 145645f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(delta >= 0); 145745f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (delta > 0) { 145845f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = iLo; i < nsegments_used-delta; i++) 145945f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i] = nsegments[i+delta]; 146045f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments_used -= delta; 146145f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 146245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 146345f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[iLo] = *seg; 146445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 146545f4e7c91119c7d01a59f5e827c67841632c9314sewardj (void)preen_nsegments(); 146645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (0) VG_(am_show_nsegments)(0,"AFTER preen (add_segment)"); 146745f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 146845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 146945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 147045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Clear out an NSegment record. */ 147145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 147245f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void init_nsegment ( /*OUT*/NSegment* seg ) 147345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 147445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->kind = SkFree; 147545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->start = 0; 147645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->end = 0; 147745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->smode = SmFixed; 147845f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->dev = 0; 147945f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->ino = 0; 1480f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom seg->mode = 0; 148145f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->offset = 0; 148245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->fnIdx = -1; 148345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->hasR = seg->hasW = seg->hasX = seg->hasT = seg->isCH = False; 148445f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 148545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 148645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Make an NSegment which holds a reservation. */ 148745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 148845f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void init_resvn ( /*OUT*/NSegment* seg, Addr start, Addr end ) 148945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 149045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(start < end); 149145f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 149245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(end+1)); 149345f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment(seg); 149445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->kind = SkResvn; 149545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->start = start; 149645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg->end = end; 149745f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 149845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 149945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 150045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 150145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 150245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Startup, including reading /proc/self/maps. ---*/ 150345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 150445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 150545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 150645f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic void read_maps_callback ( Addr addr, SizeT len, UInt prot, 1507c4431bfe04c7490ea2d74939d222d87f13f30960njn ULong dev, ULong ino, Off64T offset, 1508dbb3584f591710a15a437918c0fc27e300993566florian const HChar* filename ) 150945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 151045f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 151145f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 151245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = addr; 151345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = addr+len-1; 151445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.dev = dev; 151545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.ino = ino; 151645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.offset = offset; 151745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = toBool(prot & VKI_PROT_READ); 151845f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = toBool(prot & VKI_PROT_WRITE); 151945f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = toBool(prot & VKI_PROT_EXEC); 152045f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasT = False; 152145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1522981ffbd4d8f303856a0183e801b934ed7e3cd957florian /* A segment in the initial /proc/self/maps is considered a FileV 1523981ffbd4d8f303856a0183e801b934ed7e3cd957florian segment if either it has a file name associated with it or both its 1524981ffbd4d8f303856a0183e801b934ed7e3cd957florian device and inode numbers are != 0. See bug #124528. */ 152545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkAnonV; 1526981ffbd4d8f303856a0183e801b934ed7e3cd957florian if (filename || (dev != 0 && ino != 0)) 1527c2fe246d0d85a81c1f63ad3e6f7496667e2f6711sewardj seg.kind = SkFileV; 152838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 152938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj# if defined(VGO_darwin) 1530f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme no dev/ino on darwin 1531f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (offset != 0) 153238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj seg.kind = SkFileV; 153338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj# endif // defined(VGO_darwin) 153438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 153538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj# if defined(VGP_arm_linux) 153638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj /* The standard handling of entries read from /proc/self/maps will 153738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj cause the faked up commpage segment to have type SkAnonV, which 153838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj is a problem because it contains code we want the client to 153938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj execute, and so later m_translate will segfault the client when 154038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj it tries to go in there. Hence change the ownership of it here 154138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj to the client (SkAnonC). The least-worst kludge I could think 154238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj of. */ 154338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj if (addr == ARM_LINUX_FAKE_COMMPAGE_START 154438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj && addr + len == ARM_LINUX_FAKE_COMMPAGE_END1 154538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj && seg.kind == SkAnonV) 154638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj seg.kind = SkAnonC; 154738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj# endif // defined(VGP_arm_linux) 154838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 1549c2fe246d0d85a81c1f63ad3e6f7496667e2f6711sewardj if (filename) 15504ecd48360351f666f008148c12a24cbda455c6b1florian seg.fnIdx = ML_(am_allocate_segname)( filename ); 155145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 155245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (0) show_nsegment( 2,0, &seg ); 155345f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 1554548be6d64c58729588a559b1512ad7625bc1b86esewardj} 1555548be6d64c58729588a559b1512ad7625bc1b86esewardj 155682e7a5439ce882f99cdb49bc064616d95124738dflorianBool 155782e7a5439ce882f99cdb49bc064616d95124738dflorianVG_(am_is_valid_for_aspacem_minAddr)( Addr addr, const HChar **errmsg ) 155882e7a5439ce882f99cdb49bc064616d95124738dflorian{ 1559d738b46bd7dd65fe55736744fb3be1f0159d3a58florian const Addr min = VKI_PAGE_SIZE; 156082e7a5439ce882f99cdb49bc064616d95124738dflorian#if VG_WORDSIZE == 4 156182e7a5439ce882f99cdb49bc064616d95124738dflorian const Addr max = 0x40000000; // 1Gb 156282e7a5439ce882f99cdb49bc064616d95124738dflorian#else 156382e7a5439ce882f99cdb49bc064616d95124738dflorian const Addr max = 0x200000000; // 8Gb 156482e7a5439ce882f99cdb49bc064616d95124738dflorian#endif 156582e7a5439ce882f99cdb49bc064616d95124738dflorian Bool ok = VG_IS_PAGE_ALIGNED(addr) && addr >= min && addr <= max; 156682e7a5439ce882f99cdb49bc064616d95124738dflorian 156782e7a5439ce882f99cdb49bc064616d95124738dflorian if (errmsg) { 156882e7a5439ce882f99cdb49bc064616d95124738dflorian *errmsg = ""; 156982e7a5439ce882f99cdb49bc064616d95124738dflorian if (! ok) { 157082e7a5439ce882f99cdb49bc064616d95124738dflorian const HChar fmt[] = "Must be a page aligned address between " 157182e7a5439ce882f99cdb49bc064616d95124738dflorian "0x%lx and 0x%lx"; 157282e7a5439ce882f99cdb49bc064616d95124738dflorian static HChar buf[sizeof fmt + 2 * 16]; // large enough 157382e7a5439ce882f99cdb49bc064616d95124738dflorian ML_(am_sprintf)(buf, fmt, min, max); 157482e7a5439ce882f99cdb49bc064616d95124738dflorian *errmsg = buf; 157582e7a5439ce882f99cdb49bc064616d95124738dflorian } 157682e7a5439ce882f99cdb49bc064616d95124738dflorian } 157782e7a5439ce882f99cdb49bc064616d95124738dflorian return ok; 157882e7a5439ce882f99cdb49bc064616d95124738dflorian} 157982e7a5439ce882f99cdb49bc064616d95124738dflorian 158038a74d2cc4670e3eb559adff51a376cd6ec98005philippe/* See description in pub_core_aspacemgr.h */ 158145f4e7c91119c7d01a59f5e827c67841632c9314sewardjAddr VG_(am_startup) ( Addr sp_at_startup ) 158245f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 158345f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 158438a74d2cc4670e3eb559adff51a376cd6ec98005philippe Addr suggested_clstack_end; 158545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 158645f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sizeof(Word) == sizeof(void*)); 158745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sizeof(Addr) == sizeof(void*)); 158845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sizeof(SizeT) == sizeof(void*)); 158945f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sizeof(SSizeT) == sizeof(void*)); 159045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1591346ee2f7978bf2ab1ead4982e56870da276fc44bflorian /* Initialise the string table for segment names. */ 15924ecd48360351f666f008148c12a24cbda455c6b1florian ML_(am_segnames_init)(); 1593346ee2f7978bf2ab1ead4982e56870da276fc44bflorian 1594419060073e7943846cc9e0bcdcb25258d90da2dcsewardj /* Check that we can store the largest imaginable dev, ino and 1595419060073e7943846cc9e0bcdcb25258d90da2dcsewardj offset numbers in an NSegment. */ 1596419060073e7943846cc9e0bcdcb25258d90da2dcsewardj aspacem_assert(sizeof(seg.dev) == 8); 1597419060073e7943846cc9e0bcdcb25258d90da2dcsewardj aspacem_assert(sizeof(seg.ino) == 8); 1598419060073e7943846cc9e0bcdcb25258d90da2dcsewardj aspacem_assert(sizeof(seg.offset) == 8); 1599419060073e7943846cc9e0bcdcb25258d90da2dcsewardj aspacem_assert(sizeof(seg.mode) == 4); 160045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 160145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Add a single interval covering the entire address space. */ 160245f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment(&seg); 160345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkFree; 160445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = Addr_MIN; 160545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = Addr_MAX; 160645f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[0] = seg; 160745f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments_used = 1; 160845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1609e4d78123089e55bec64a4f848bdc09556192e259philippe aspacem_minAddr = VG_(clo_aspacem_minAddr); 1610e4d78123089e55bec64a4f848bdc09556192e259philippe 1611f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if defined(VGO_darwin) 1612f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 1613f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# if VG_WORDSIZE == 4 1614f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_maxAddr = (Addr) 0xffffffff; 1615f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 1616f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_cStart = aspacem_minAddr; 1617f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_vStart = 0xf0000000; // 0xc0000000..0xf0000000 available 1618f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# else 1619f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_maxAddr = (Addr) 0x7fffffffffff; 1620f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 1621f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_cStart = aspacem_minAddr; 1622f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_vStart = 0x700000000000; // 0x7000:00000000..0x7fff:5c000000 avail 1623f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // 0x7fff:5c000000..0x7fff:ffe00000? is stack, dyld, shared cache 1624f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# endif 1625f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 162638a74d2cc4670e3eb559adff51a376cd6ec98005philippe suggested_clstack_end = -1; // ignored; Mach-O specifies its stack 1627f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 16288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#elif defined(VGO_solaris) 16298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# if VG_WORDSIZE == 4 16308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* 16318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Intended address space partitioning: 16328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 16338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ,--------------------------------, 0x00000000 16348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | initial stack given to V by OS | 16378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 0x08000000 16388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | client text | 16398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | client stack | 16448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 0x38000000 16458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | V's text | 16468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | dynamic shared objects | 16518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj '--------------------------------' 0xffffffff 16528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 16538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */ 16548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 16558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Anonymous pages need to fit under user limit (USERLIMIT32) 16568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj which is 4KB + 16MB below the top of the 32-bit range. */ 16578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# ifdef ENABLE_INNER 16588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_maxAddr = (Addr)0x4fffffff; // 1.25GB 16598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_vStart = (Addr)0x40000000; // 1GB 16608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# else 16618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_maxAddr = (Addr)0xfefff000 - 1; // 4GB - 16MB - 4KB 16628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_vStart = (Addr)0x50000000; // 1.25GB 16638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# endif 16648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# elif VG_WORDSIZE == 8 16658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* 16668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Intended address space partitioning: 16678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 16688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ,--------------------------------, 0x00000000_00000000 16698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 0x00000000_00400000 16718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | client text | 16728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | client stack | 16778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 0x00000000_38000000 16788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | V's text | 16798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | dynamic shared objects | 16838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 0x0000000f_ffffffff 16848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | | 16868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj |--------------------------------| 16878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj | initial stack given to V by OS | 16888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj '--------------------------------' 0xffffffff_ffffffff 16898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 16908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */ 16918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 16928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Kernel likes to place objects at the end of the address space. 16938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj However accessing memory beyond 64GB makes memcheck slow 16948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (see memcheck/mc_main.c, internal representation). Therefore: 16958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj - mmapobj() syscall is emulated so that libraries are subject to 16968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Valgrind's aspacemgr control 16978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj - Kernel shared pages (such as schedctl and hrt) are left as they are 16988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj because kernel cannot be told where they should be put */ 16998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# ifdef ENABLE_INNER 17008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_maxAddr = (Addr) 0x00000007ffffffff; // 32GB 17018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_vStart = (Addr) 0x0000000400000000; // 16GB 17028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# else 17038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_maxAddr = (Addr) 0x0000000fffffffff; // 64GB 17048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_vStart = (Addr) 0x0000000800000000; // 32GB 17058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# endif 17068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# else 17078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# error "Unknown word size" 17088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# endif 17098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 17108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_cStart = aspacem_minAddr; 17118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# ifdef ENABLE_INNER 17128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj suggested_clstack_end = (Addr) 0x27ff0000 - 1; // 64kB below V's text 17138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# else 17148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj suggested_clstack_end = (Addr) 0x37ff0000 - 1; // 64kB below V's text 17158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# endif 17168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 17178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else 1718f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 171945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Establish address limits and block out unusable parts 172045f4e7c91119c7d01a59f5e827c67841632c9314sewardj accordingly. */ 172145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 172245f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", 1723a5e06c36bf9d93461bc8c4351e960888020ea1c4florian " sp_at_startup = 0x%010lx (supplied)\n", 1724a5e06c36bf9d93461bc8c4351e960888020ea1c4florian sp_at_startup ); 172545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 172645f4e7c91119c7d01a59f5e827c67841632c9314sewardj# if VG_WORDSIZE == 8 17276805a4a08d862003b6039493eec1b2e6b7829e78sewardj aspacem_maxAddr = (Addr)0x1000000000ULL - 1; // 64G 172870c91dd9e5768adb7195fe7280aac359c7848984sewardj# ifdef ENABLE_INNER 1729420c6555d36e7ad19cf3b9e068397435d4acca51sewardj { Addr cse = VG_PGROUNDDN( sp_at_startup ) - 1; 1730420c6555d36e7ad19cf3b9e068397435d4acca51sewardj if (aspacem_maxAddr > cse) 1731420c6555d36e7ad19cf3b9e068397435d4acca51sewardj aspacem_maxAddr = cse; 1732420c6555d36e7ad19cf3b9e068397435d4acca51sewardj } 173370c91dd9e5768adb7195fe7280aac359c7848984sewardj# endif 173445f4e7c91119c7d01a59f5e827c67841632c9314sewardj# else 173570c91dd9e5768adb7195fe7280aac359c7848984sewardj aspacem_maxAddr = VG_PGROUNDDN( sp_at_startup ) - 1; 173645f4e7c91119c7d01a59f5e827c67841632c9314sewardj# endif 173745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1738e4d78123089e55bec64a4f848bdc09556192e259philippe aspacem_cStart = aspacem_minAddr; 1739d4f5aac98c40fb66d193587d72d024e86cdf3075philippe aspacem_vStart = VG_PGROUNDUP(aspacem_minAddr 1740d4f5aac98c40fb66d193587d72d024e86cdf3075philippe + (aspacem_maxAddr - aspacem_minAddr + 1) / 2); 174145f4e7c91119c7d01a59f5e827c67841632c9314sewardj# ifdef ENABLE_INNER 174245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_vStart -= 0x10000000; // 256M 174345f4e7c91119c7d01a59f5e827c67841632c9314sewardj# endif 174445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 174538a74d2cc4670e3eb559adff51a376cd6ec98005philippe suggested_clstack_end = aspacem_maxAddr - 16*1024*1024ULL 174645f4e7c91119c7d01a59f5e827c67841632c9314sewardj + VKI_PAGE_SIZE; 174745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 17488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif 1749f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 175045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_minAddr)); 175145f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_maxAddr + 1)); 175245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_cStart)); 175345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_vStart)); 175438a74d2cc4670e3eb559adff51a376cd6ec98005philippe aspacem_assert(VG_IS_PAGE_ALIGNED(suggested_clstack_end + 1)); 175545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 175645f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", 1757a5e06c36bf9d93461bc8c4351e960888020ea1c4florian " minAddr = 0x%010lx (computed)\n", 1758a5e06c36bf9d93461bc8c4351e960888020ea1c4florian aspacem_minAddr); 175945f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", 1760a5e06c36bf9d93461bc8c4351e960888020ea1c4florian " maxAddr = 0x%010lx (computed)\n", 1761a5e06c36bf9d93461bc8c4351e960888020ea1c4florian aspacem_maxAddr); 176245f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", 1763a5e06c36bf9d93461bc8c4351e960888020ea1c4florian " cStart = 0x%010lx (computed)\n", 1764a5e06c36bf9d93461bc8c4351e960888020ea1c4florian aspacem_cStart); 176545f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", 1766a5e06c36bf9d93461bc8c4351e960888020ea1c4florian " vStart = 0x%010lx (computed)\n", 1767a5e06c36bf9d93461bc8c4351e960888020ea1c4florian aspacem_vStart); 176845f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", 1769a5e06c36bf9d93461bc8c4351e960888020ea1c4florian "suggested_clstack_end = 0x%010lx (computed)\n", 1770a5e06c36bf9d93461bc8c4351e960888020ea1c4florian suggested_clstack_end); 177145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 177245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (aspacem_cStart > Addr_MIN) { 177345f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_resvn(&seg, Addr_MIN, aspacem_cStart-1); 177445f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment(&seg); 177545f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 177645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (aspacem_maxAddr < Addr_MAX) { 177745f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_resvn(&seg, aspacem_maxAddr+1, Addr_MAX); 177845f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment(&seg); 177945f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 178045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 178145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Create a 1-page reservation at the notional initial 178245f4e7c91119c7d01a59f5e827c67841632c9314sewardj client/valgrind boundary. This isn't strictly necessary, but 178345f4e7c91119c7d01a59f5e827c67841632c9314sewardj because the advisor does first-fit and starts searches for 178445f4e7c91119c7d01a59f5e827c67841632c9314sewardj valgrind allocations at the boundary, this is kind of necessary 178545f4e7c91119c7d01a59f5e827c67841632c9314sewardj in order to get it to start allocating in the right place. */ 178645f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_resvn(&seg, aspacem_vStart, aspacem_vStart + VKI_PAGE_SIZE - 1); 178745f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment(&seg); 178845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 178945f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(am_show_nsegments)(2, "Initial layout"); 179045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 179145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(2, "aspacem", "Reading /proc/self/maps\n"); 1792cb249ab3febb3757a0b0582be21952efacf415e5sewardj parse_procselfmaps( read_maps_callback, NULL ); 179338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj /* NB: on arm-linux, parse_procselfmaps automagically kludges up 179438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj (iow, hands to its callbacks) a description of the ARM Commpage, 179538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj since that's not listed in /proc/self/maps (kernel bug IMO). We 179638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj have to fake up its existence in parse_procselfmaps and not 179738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj merely add it here as an extra segment, because doing the latter 179838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj causes sync checking to fail: we see we have an extra segment in 179938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj the segments array, which isn't listed in /proc/self/maps. 180038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj Hence we must make it appear that /proc/self/maps contained this 180138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj segment all along. Sigh. */ 180245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 180345f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(am_show_nsegments)(2, "With contents of /proc/self/maps"); 180445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 180545f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 180638a74d2cc4670e3eb559adff51a376cd6ec98005philippe return suggested_clstack_end; 180745f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 180845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 180945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 181045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 181145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 181245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- The core query-notify mechanism. ---*/ 181345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 181445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 181545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 181645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Query aspacem to ask where a mapping should go. */ 181745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 18183297124fa2116737066ac3cd709f18fdd5405163florianAddr VG_(am_get_advisory) ( const MapRequest* req, 18193297124fa2116737066ac3cd709f18fdd5405163florian Bool forClient, 182045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*OUT*/Bool* ok ) 182145f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 182245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* This function implements allocation policy. 182345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 182445f4e7c91119c7d01a59f5e827c67841632c9314sewardj The nature of the allocation request is determined by req, which 182545f4e7c91119c7d01a59f5e827c67841632c9314sewardj specifies the start and length of the request and indicates 182645f4e7c91119c7d01a59f5e827c67841632c9314sewardj whether the start address is mandatory, a hint, or irrelevant, 182745f4e7c91119c7d01a59f5e827c67841632c9314sewardj and by forClient, which says whether this is for the client or 182845f4e7c91119c7d01a59f5e827c67841632c9314sewardj for V. 182945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 183045f4e7c91119c7d01a59f5e827c67841632c9314sewardj Return values: the request can be vetoed (*ok is set to False), 183145f4e7c91119c7d01a59f5e827c67841632c9314sewardj in which case the caller should not attempt to proceed with 183245f4e7c91119c7d01a59f5e827c67841632c9314sewardj making the mapping. Otherwise, *ok is set to True, the caller 183345f4e7c91119c7d01a59f5e827c67841632c9314sewardj may proceed, and the preferred address at which the mapping 183445f4e7c91119c7d01a59f5e827c67841632c9314sewardj should happen is returned. 183545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 183645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Note that this is an advisory system only: the kernel can in 183745f4e7c91119c7d01a59f5e827c67841632c9314sewardj fact do whatever it likes as far as placement goes, and we have 183845f4e7c91119c7d01a59f5e827c67841632c9314sewardj no absolute control over it. 183945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 184045f4e7c91119c7d01a59f5e827c67841632c9314sewardj Allocations will never be granted in a reserved area. 184145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 184245f4e7c91119c7d01a59f5e827c67841632c9314sewardj The Default Policy is: 184345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 184445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Search the address space for two free intervals: one of them 184545f4e7c91119c7d01a59f5e827c67841632c9314sewardj big enough to contain the request without regard to the 184645f4e7c91119c7d01a59f5e827c67841632c9314sewardj specified address (viz, as if it was a floating request) and 184745f4e7c91119c7d01a59f5e827c67841632c9314sewardj the other being able to contain the request at the specified 184845f4e7c91119c7d01a59f5e827c67841632c9314sewardj address (viz, as if were a fixed request). Then, depending on 184945f4e7c91119c7d01a59f5e827c67841632c9314sewardj the outcome of the search and the kind of request made, decide 185045f4e7c91119c7d01a59f5e827c67841632c9314sewardj whether the request is allowable and what address to advise. 185145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 185245f4e7c91119c7d01a59f5e827c67841632c9314sewardj The Default Policy is overriden by Policy Exception #1: 185345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 185445f4e7c91119c7d01a59f5e827c67841632c9314sewardj If the request is for a fixed client map, we are prepared to 185545f4e7c91119c7d01a59f5e827c67841632c9314sewardj grant it providing all areas inside the request are either 185645f4e7c91119c7d01a59f5e827c67841632c9314sewardj free, reservations, or mappings belonging to the client. In 185745f4e7c91119c7d01a59f5e827c67841632c9314sewardj other words we are prepared to let the client trash its own 185845f4e7c91119c7d01a59f5e827c67841632c9314sewardj mappings if it wants to. 185945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1860caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj The Default Policy is overriden by Policy Exception #2: 186145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1862caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj If the request is for a hinted client map, we are prepared to 1863caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj grant it providing all areas inside the request are either 1864caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj free or reservations. In other words we are prepared to let 1865caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj the client have a hinted mapping anywhere it likes provided 1866caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj it does not trash either any of its own mappings or any of 1867caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj valgrind's mappings. 186845f4e7c91119c7d01a59f5e827c67841632c9314sewardj */ 186945f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i, j; 187045f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr holeStart, holeEnd, holeLen; 187145f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool fixed_not_required; 187245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 18738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris) 18748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Addr startPoint = forClient ? aspacem_vStart - 1 : aspacem_maxAddr - 1; 18758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else 187645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr startPoint = forClient ? aspacem_cStart : aspacem_vStart; 18778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif /* VGO_solaris */ 187845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 18798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Addr reqStart = req->rkind==MFixed || req->rkind==MHint ? req->start : 0; 188045f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr reqEnd = reqStart + req->len - 1; 188145f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr reqLen = req->len; 188245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 188345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* These hold indices for segments found during search, or -1 if not 188445f4e7c91119c7d01a59f5e827c67841632c9314sewardj found. */ 188545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int floatIdx = -1; 188645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int fixedIdx = -1; 188745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 188845f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments_used > 0); 188945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 189045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (0) { 189145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(am_show_nsegments)(0,"getAdvisory"); 1892a5e06c36bf9d93461bc8c4351e960888020ea1c4florian VG_(debugLog)(0,"aspacem", "getAdvisory 0x%lx %lu\n", 1893a5e06c36bf9d93461bc8c4351e960888020ea1c4florian req->start, req->len); 189445f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 189545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 189645f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Reject zero-length requests */ 189745f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (req->len == 0) { 189845f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = False; 189945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return 0; 190045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 190145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 190245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Reject wraparounds */ 1903e354a1fd9e4a4ca836d3c6bbf159b5811fa25124florian if (req->start + req->len < req->start) { 190445f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = False; 190545f4e7c91119c7d01a59f5e827c67841632c9314sewardj return 0; 190645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 190779048ce723a3463c70257ce647f04b111de71863sewardj 190845f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* ------ Implement Policy Exception #1 ------ */ 190945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1910caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj if (forClient && req->rkind == MFixed) { 191145f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int iLo = find_nsegment_idx(reqStart); 191245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int iHi = find_nsegment_idx(reqEnd); 191345f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool allow = True; 191445f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = iLo; i <= iHi; i++) { 191545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].kind == SkFree 191645f4e7c91119c7d01a59f5e827c67841632c9314sewardj || nsegments[i].kind == SkFileC 191745f4e7c91119c7d01a59f5e827c67841632c9314sewardj || nsegments[i].kind == SkAnonC 19181340c35bebb175c6d158361596ee6171b4cfc2a2tom || nsegments[i].kind == SkShmC 191945f4e7c91119c7d01a59f5e827c67841632c9314sewardj || nsegments[i].kind == SkResvn) { 192045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* ok */ 192145f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else { 192245f4e7c91119c7d01a59f5e827c67841632c9314sewardj allow = False; 192345f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 192445f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 192545f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 192645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (allow) { 192745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Acceptable. Granted. */ 192845f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = True; 192945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return reqStart; 193045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 1931caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj /* Not acceptable. Fail. */ 1932caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj *ok = False; 1933caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj return 0; 1934caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj } 1935caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj 1936caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj /* ------ Implement Policy Exception #2 ------ */ 1937caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj 1938caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj if (forClient && req->rkind == MHint) { 1939caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj Int iLo = find_nsegment_idx(reqStart); 1940caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj Int iHi = find_nsegment_idx(reqEnd); 1941caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj Bool allow = True; 1942caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj for (i = iLo; i <= iHi; i++) { 1943caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj if (nsegments[i].kind == SkFree 1944caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj || nsegments[i].kind == SkResvn) { 1945caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj /* ok */ 1946caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj } else { 1947caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj allow = False; 1948caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj break; 1949caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj } 1950caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj } 1951caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj if (allow) { 1952caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj /* Acceptable. Granted. */ 1953caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj *ok = True; 1954caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj return reqStart; 195545f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 1956caf971dea8c108cbd200dce1c6a94e96bf2e91b1sewardj /* Not acceptable. Fall through to the default policy. */ 1957548be6d64c58729588a559b1512ad7625bc1b86esewardj } 1958548be6d64c58729588a559b1512ad7625bc1b86esewardj 195945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* ------ Implement the Default Policy ------ */ 1960548be6d64c58729588a559b1512ad7625bc1b86esewardj 196145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Don't waste time looking for a fixed match if not requested to. */ 19628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj fixed_not_required = req->rkind == MAny || req->rkind == MAlign; 196345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 196445f4e7c91119c7d01a59f5e827c67841632c9314sewardj i = find_nsegment_idx(startPoint); 196545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 19668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris) 19678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define UPDATE_INDEX(index) \ 19688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (index)--; \ 19698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if ((index) <= 0) \ 19708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (index) = nsegments_used - 1; 19718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define ADVISE_ADDRESS(segment) \ 19728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj VG_PGROUNDDN((segment)->end + 1 - reqLen) 19738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define ADVISE_ADDRESS_ALIGNED(segment) \ 19748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj VG_ROUNDDN((segment)->end + 1 - reqLen, req->start) 19758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 19768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#else 19778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 19788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define UPDATE_INDEX(index) \ 19798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (index)++; \ 19808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if ((index) >= nsegments_used) \ 19818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (index) = 0; 19828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define ADVISE_ADDRESS(segment) \ 19838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (segment)->start 19848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj# define ADVISE_ADDRESS_ALIGNED(segment) \ 19858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj VG_ROUNDUP((segment)->start, req->start) 19868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif /* VGO_solaris */ 19878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 198845f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Examine holes from index i back round to i-1. Record the 198945f4e7c91119c7d01a59f5e827c67841632c9314sewardj index first fixed hole and the first floating hole which would 199045f4e7c91119c7d01a59f5e827c67841632c9314sewardj satisfy the request. */ 199145f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (j = 0; j < nsegments_used; j++) { 199245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 199345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].kind != SkFree) { 19948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj UPDATE_INDEX(i); 199579048ce723a3463c70257ce647f04b111de71863sewardj continue; 199645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 1997548be6d64c58729588a559b1512ad7625bc1b86esewardj 199845f4e7c91119c7d01a59f5e827c67841632c9314sewardj holeStart = nsegments[i].start; 199945f4e7c91119c7d01a59f5e827c67841632c9314sewardj holeEnd = nsegments[i].end; 2000548be6d64c58729588a559b1512ad7625bc1b86esewardj 200145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Stay sane .. */ 200245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(holeStart <= holeEnd); 200345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(aspacem_minAddr <= holeStart); 200445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(holeEnd <= aspacem_maxAddr); 2005548be6d64c58729588a559b1512ad7625bc1b86esewardj 20068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (req->rkind == MAlign) { 20078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj holeStart = VG_ROUNDUP(holeStart, req->start); 20088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (holeStart >= holeEnd) { 20098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* This hole can't be used. */ 20108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj UPDATE_INDEX(i); 20118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj continue; 20128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 20138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 20148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 201545f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* See if it's any use to us. */ 201645f4e7c91119c7d01a59f5e827c67841632c9314sewardj holeLen = holeEnd - holeStart + 1; 2017548be6d64c58729588a559b1512ad7625bc1b86esewardj 201845f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (fixedIdx == -1 && holeStart <= reqStart && reqEnd <= holeEnd) 201945f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixedIdx = i; 202045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 202145f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (floatIdx == -1 && holeLen >= reqLen) 202245f4e7c91119c7d01a59f5e827c67841632c9314sewardj floatIdx = i; 202345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 202445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Don't waste time searching once we've found what we wanted. */ 202545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if ((fixed_not_required || fixedIdx >= 0) && floatIdx >= 0) 202645f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 202745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 20288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj UPDATE_INDEX(i); 202979048ce723a3463c70257ce647f04b111de71863sewardj } 2030548be6d64c58729588a559b1512ad7625bc1b86esewardj 203145f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(fixedIdx >= -1 && fixedIdx < nsegments_used); 203245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (fixedIdx >= 0) 203345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments[fixedIdx].kind == SkFree); 203479048ce723a3463c70257ce647f04b111de71863sewardj 203545f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(floatIdx >= -1 && floatIdx < nsegments_used); 203645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (floatIdx >= 0) 203745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments[floatIdx].kind == SkFree); 203845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 203945f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 204045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 204145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Now see if we found anything which can satisfy the request. */ 204245f4e7c91119c7d01a59f5e827c67841632c9314sewardj switch (req->rkind) { 204345f4e7c91119c7d01a59f5e827c67841632c9314sewardj case MFixed: 204445f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (fixedIdx >= 0) { 204545f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = True; 204645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return req->start; 204745f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else { 204845f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = False; 204945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return 0; 205045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 205145f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 205245f4e7c91119c7d01a59f5e827c67841632c9314sewardj case MHint: 205345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (fixedIdx >= 0) { 205445f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = True; 205545f4e7c91119c7d01a59f5e827c67841632c9314sewardj return req->start; 205645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 205745f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (floatIdx >= 0) { 205845f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = True; 20598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return ADVISE_ADDRESS(&nsegments[floatIdx]); 206045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 206145f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = False; 206245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return 0; 206345f4e7c91119c7d01a59f5e827c67841632c9314sewardj case MAny: 206445f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (floatIdx >= 0) { 206545f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = True; 20668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return ADVISE_ADDRESS(&nsegments[floatIdx]); 20678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 20688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj *ok = False; 20698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 0; 20708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj case MAlign: 20718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (floatIdx >= 0) { 20728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj *ok = True; 20738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return ADVISE_ADDRESS_ALIGNED(&nsegments[floatIdx]); 207445f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 207545f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = False; 207645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return 0; 207745f4e7c91119c7d01a59f5e827c67841632c9314sewardj default: 207845f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 2079f6ec8ec39b3977f5a8ce446353ea990ae2c6e4b2njn } 208045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 208145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*NOTREACHED*/ 2082297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ML_(am_barf)("getAdvisory: unknown request kind"); 208345f4e7c91119c7d01a59f5e827c67841632c9314sewardj *ok = False; 208445f4e7c91119c7d01a59f5e827c67841632c9314sewardj return 0; 20858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 20868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef UPDATE_INDEX 20878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef ADVISE_ADDRESS 20888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#undef ADVISE_ADDRESS_ALIGNED 2089548be6d64c58729588a559b1512ad7625bc1b86esewardj} 2090548be6d64c58729588a559b1512ad7625bc1b86esewardj 209145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Convenience wrapper for VG_(am_get_advisory) for client floating or 209245f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixed requests. If start is zero, a floating request is issued; if 209345f4e7c91119c7d01a59f5e827c67841632c9314sewardj nonzero, a fixed request at that address is issued. Same comments 209445f4e7c91119c7d01a59f5e827c67841632c9314sewardj about return values apply. */ 2095548be6d64c58729588a559b1512ad7625bc1b86esewardj 209645f4e7c91119c7d01a59f5e827c67841632c9314sewardjAddr VG_(am_get_advisory_client_simple) ( Addr start, SizeT len, 209745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /*OUT*/Bool* ok ) 2098548be6d64c58729588a559b1512ad7625bc1b86esewardj{ 209945f4e7c91119c7d01a59f5e827c67841632c9314sewardj MapRequest mreq; 210045f4e7c91119c7d01a59f5e827c67841632c9314sewardj mreq.rkind = start==0 ? MAny : MFixed; 210145f4e7c91119c7d01a59f5e827c67841632c9314sewardj mreq.start = start; 210245f4e7c91119c7d01a59f5e827c67841632c9314sewardj mreq.len = len; 2103515e26933c61eed21ba8d74ecdfc89c217832fedphilippe return VG_(am_get_advisory)( &mreq, True/*forClient*/, ok ); 2104548be6d64c58729588a559b1512ad7625bc1b86esewardj} 2105548be6d64c58729588a559b1512ad7625bc1b86esewardj 210615e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe/* Similar to VG_(am_find_nsegment) but only returns free segments. */ 210715e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippestatic NSegment const * VG_(am_find_free_nsegment) ( Addr a ) 210815e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe{ 210915e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe Int i = find_nsegment_idx(a); 211015e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe aspacem_assert(i >= 0 && i < nsegments_used); 211115e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe aspacem_assert(nsegments[i].start <= a); 211215e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe aspacem_assert(a <= nsegments[i].end); 211315e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe if (nsegments[i].kind == SkFree) 211415e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe return &nsegments[i]; 211515e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe else 211615e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe return NULL; 211715e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe} 211815e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe 211915e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippeBool VG_(am_covered_by_single_free_segment) 212015e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe ( Addr start, SizeT len) 212115e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe{ 212215e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe NSegment const* segLo = VG_(am_find_free_nsegment)( start ); 212315e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe NSegment const* segHi = VG_(am_find_free_nsegment)( start + len - 1 ); 212415e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe 212515e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe return segLo != NULL && segHi != NULL && segLo == segHi; 212615e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe} 212715e301e2b0540fea8dd8b5410bf75d2fa0e8eac1philippe 212879048ce723a3463c70257ce647f04b111de71863sewardj 212945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Notifies aspacem that the client completed an mmap successfully. 213045f4e7c91119c7d01a59f5e827c67841632c9314sewardj The segment array is updated accordingly. If the returned Bool is 213145f4e7c91119c7d01a59f5e827c67841632c9314sewardj True, the caller should immediately discard translations from the 213245f4e7c91119c7d01a59f5e827c67841632c9314sewardj specified address range. */ 213379048ce723a3463c70257ce647f04b111de71863sewardj 213445f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool 213545f4e7c91119c7d01a59f5e827c67841632c9314sewardjVG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags, 2136274461dcb67f680196c97e8afb7028a79b97dcb7sewardj Int fd, Off64T offset ) 2137548be6d64c58729588a559b1512ad7625bc1b86esewardj{ 213845f4e7c91119c7d01a59f5e827c67841632c9314sewardj HChar buf[VKI_PATH_MAX]; 2139419060073e7943846cc9e0bcdcb25258d90da2dcsewardj ULong dev, ino; 2140f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom UInt mode; 214145f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 214245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool needDiscard; 214345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 214445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(len > 0); 214545f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(a)); 214645f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2147274461dcb67f680196c97e8afb7028a79b97dcb7sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(offset)); 214845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 214945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Discard is needed if any of the just-trashed range had T. */ 215045f4e7c91119c7d01a59f5e827c67841632c9314sewardj needDiscard = any_Ts_in_range( a, len ); 215145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 215245f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 215345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = (flags & VKI_MAP_ANONYMOUS) ? SkAnonC : SkFileC; 215445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = a; 215545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = a + len - 1; 215645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = toBool(prot & VKI_PROT_READ); 215745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = toBool(prot & VKI_PROT_WRITE); 215845f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = toBool(prot & VKI_PROT_EXEC); 215945f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!(flags & VKI_MAP_ANONYMOUS)) { 21604395ad459576d155df4270a96bc46279c43d498anjn // Nb: We ignore offset requests in anonymous mmaps (see bug #126722) 2161dadff0a77b92b9c81648850d628ab781b44965f9tom seg.offset = offset; 2162dad944add53e6361751c6832066c00c456854622njn if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { 216345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.dev = dev; 216445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.ino = ino; 2165f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom seg.mode = mode; 216645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 2167dad944add53e6361751c6832066c00c456854622njn if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { 21684ecd48360351f666f008148c12a24cbda455c6b1florian seg.fnIdx = ML_(am_allocate_segname)( buf ); 216945f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 217079048ce723a3463c70257ce647f04b111de71863sewardj } 217145f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 217245f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 217345f4e7c91119c7d01a59f5e827c67841632c9314sewardj return needDiscard; 2174548be6d64c58729588a559b1512ad7625bc1b86esewardj} 2175548be6d64c58729588a559b1512ad7625bc1b86esewardj 21761340c35bebb175c6d158361596ee6171b4cfc2a2tom/* Notifies aspacem that the client completed a shmat successfully. 21771340c35bebb175c6d158361596ee6171b4cfc2a2tom The segment array is updated accordingly. If the returned Bool is 21781340c35bebb175c6d158361596ee6171b4cfc2a2tom True, the caller should immediately discard translations from the 21791340c35bebb175c6d158361596ee6171b4cfc2a2tom specified address range. */ 21801340c35bebb175c6d158361596ee6171b4cfc2a2tom 21811340c35bebb175c6d158361596ee6171b4cfc2a2tomBool 21821340c35bebb175c6d158361596ee6171b4cfc2a2tomVG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ) 21831340c35bebb175c6d158361596ee6171b4cfc2a2tom{ 21841340c35bebb175c6d158361596ee6171b4cfc2a2tom NSegment seg; 21851340c35bebb175c6d158361596ee6171b4cfc2a2tom Bool needDiscard; 21861340c35bebb175c6d158361596ee6171b4cfc2a2tom 21871340c35bebb175c6d158361596ee6171b4cfc2a2tom aspacem_assert(len > 0); 21881340c35bebb175c6d158361596ee6171b4cfc2a2tom aspacem_assert(VG_IS_PAGE_ALIGNED(a)); 21891340c35bebb175c6d158361596ee6171b4cfc2a2tom aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 21901340c35bebb175c6d158361596ee6171b4cfc2a2tom 21911340c35bebb175c6d158361596ee6171b4cfc2a2tom /* Discard is needed if any of the just-trashed range had T. */ 21921340c35bebb175c6d158361596ee6171b4cfc2a2tom needDiscard = any_Ts_in_range( a, len ); 21931340c35bebb175c6d158361596ee6171b4cfc2a2tom 21941340c35bebb175c6d158361596ee6171b4cfc2a2tom init_nsegment( &seg ); 21951340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.kind = SkShmC; 21961340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.start = a; 21971340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.end = a + len - 1; 21981340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.offset = 0; 21991340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.hasR = toBool(prot & VKI_PROT_READ); 22001340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.hasW = toBool(prot & VKI_PROT_WRITE); 22011340c35bebb175c6d158361596ee6171b4cfc2a2tom seg.hasX = toBool(prot & VKI_PROT_EXEC); 22021340c35bebb175c6d158361596ee6171b4cfc2a2tom add_segment( &seg ); 22031340c35bebb175c6d158361596ee6171b4cfc2a2tom AM_SANITY_CHECK; 22041340c35bebb175c6d158361596ee6171b4cfc2a2tom return needDiscard; 22051340c35bebb175c6d158361596ee6171b4cfc2a2tom} 22061340c35bebb175c6d158361596ee6171b4cfc2a2tom 220745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Notifies aspacem that an mprotect was completed successfully. The 220845f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment array is updated accordingly. Note, as with 220945f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(am_notify_munmap), it is not the job of this function to reject 221045f4e7c91119c7d01a59f5e827c67841632c9314sewardj stupid mprotects, for example the client doing mprotect of 221145f4e7c91119c7d01a59f5e827c67841632c9314sewardj non-client areas. Such requests should be intercepted earlier, by 221245f4e7c91119c7d01a59f5e827c67841632c9314sewardj the syscall wrapper for mprotect. This function merely records 221345f4e7c91119c7d01a59f5e827c67841632c9314sewardj whatever it is told. If the returned Bool is True, the caller 221445f4e7c91119c7d01a59f5e827c67841632c9314sewardj should immediately discard translations from the specified address 221545f4e7c91119c7d01a59f5e827c67841632c9314sewardj range. */ 221645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 221745f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot ) 221845f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 221945f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i, iLo, iHi; 222045f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool newR, newW, newX, needDiscard; 222179048ce723a3463c70257ce647f04b111de71863sewardj 222245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 222345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2224548be6d64c58729588a559b1512ad7625bc1b86esewardj 222545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (len == 0) 222645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 2227548be6d64c58729588a559b1512ad7625bc1b86esewardj 222845f4e7c91119c7d01a59f5e827c67841632c9314sewardj newR = toBool(prot & VKI_PROT_READ); 222945f4e7c91119c7d01a59f5e827c67841632c9314sewardj newW = toBool(prot & VKI_PROT_WRITE); 223045f4e7c91119c7d01a59f5e827c67841632c9314sewardj newX = toBool(prot & VKI_PROT_EXEC); 223145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 223245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Discard is needed if we're dumping X permission */ 223345f4e7c91119c7d01a59f5e827c67841632c9314sewardj needDiscard = any_Ts_in_range( start, len ) && !newX; 223445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 223545f4e7c91119c7d01a59f5e827c67841632c9314sewardj split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi ); 223645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 223745f4e7c91119c7d01a59f5e827c67841632c9314sewardj iLo = find_nsegment_idx(start); 223845f4e7c91119c7d01a59f5e827c67841632c9314sewardj iHi = find_nsegment_idx(start + len - 1); 223945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 224045f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = iLo; i <= iHi; i++) { 224145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Apply the permissions to all relevant segments. */ 224245f4e7c91119c7d01a59f5e827c67841632c9314sewardj switch (nsegments[i].kind) { 22431340c35bebb175c6d158361596ee6171b4cfc2a2tom case SkAnonC: case SkAnonV: case SkFileC: case SkFileV: case SkShmC: 224445f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i].hasR = newR; 224545f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i].hasW = newW; 224645f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[i].hasX = newX; 224745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(sane_NSegment(&nsegments[i])); 224845f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 224945f4e7c91119c7d01a59f5e827c67841632c9314sewardj default: 225045f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 225145f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 225245f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 2253548be6d64c58729588a559b1512ad7625bc1b86esewardj 225445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Changing permissions could have made previously un-mergable 225545f4e7c91119c7d01a59f5e827c67841632c9314sewardj segments mergeable. Therefore have to re-preen them. */ 225645f4e7c91119c7d01a59f5e827c67841632c9314sewardj (void)preen_nsegments(); 225745f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 225845f4e7c91119c7d01a59f5e827c67841632c9314sewardj return needDiscard; 2259548be6d64c58729588a559b1512ad7625bc1b86esewardj} 2260548be6d64c58729588a559b1512ad7625bc1b86esewardj 226179048ce723a3463c70257ce647f04b111de71863sewardj 226245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Notifies aspacem that an munmap completed successfully. The 226345f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment array is updated accordingly. As with 2264135c9f1d417cb4b1f453b8e6786ad55b89c9143eflorian VG_(am_notify_mprotect), we merely record the given info, and don't 226545f4e7c91119c7d01a59f5e827c67841632c9314sewardj check it for sensibleness. If the returned Bool is True, the 226645f4e7c91119c7d01a59f5e827c67841632c9314sewardj caller should immediately discard translations from the specified 226745f4e7c91119c7d01a59f5e827c67841632c9314sewardj address range. */ 226845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 226945f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_notify_munmap)( Addr start, SizeT len ) 227079048ce723a3463c70257ce647f04b111de71863sewardj{ 227145f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 227245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool needDiscard; 227345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 227445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 227579048ce723a3463c70257ce647f04b111de71863sewardj 227645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (len == 0) 227779048ce723a3463c70257ce647f04b111de71863sewardj return False; 227879048ce723a3463c70257ce647f04b111de71863sewardj 227945f4e7c91119c7d01a59f5e827c67841632c9314sewardj needDiscard = any_Ts_in_range( start, len ); 228079048ce723a3463c70257ce647f04b111de71863sewardj 228145f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 228245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = start; 228345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = start + len - 1; 2284613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj 2285613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj /* The segment becomes unused (free). Segments from above 2286613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj aspacem_maxAddr were originally SkResvn and so we make them so 2287613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj again. Note, this isn't really right when the segment straddles 2288613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj the aspacem_maxAddr boundary - then really it should be split in 2289613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj two, the lower part marked as SkFree and the upper part as 2290613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj SkResvn. Ah well. */ 2291613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj if (start > aspacem_maxAddr 2292613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj && /* check previous comparison is meaningful */ 2293613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj aspacem_maxAddr < Addr_MAX) 2294613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj seg.kind = SkResvn; 22957cc2040098cb14f021e04ac44f127195b98a1c30sewardj else 22967cc2040098cb14f021e04ac44f127195b98a1c30sewardj /* Ditto for segments from below aspacem_minAddr. */ 22977cc2040098cb14f021e04ac44f127195b98a1c30sewardj if (seg.end < aspacem_minAddr && aspacem_minAddr > 0) 22987cc2040098cb14f021e04ac44f127195b98a1c30sewardj seg.kind = SkResvn; 2299613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj else 2300613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj seg.kind = SkFree; 2301613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj 230245f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 230379048ce723a3463c70257ce647f04b111de71863sewardj 230445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Unmapping could create two adjacent free segments, so a preen is 230545f4e7c91119c7d01a59f5e827c67841632c9314sewardj needed. add_segment() will do that, so no need to here. */ 230645f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 230745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return needDiscard; 230879048ce723a3463c70257ce647f04b111de71863sewardj} 230979048ce723a3463c70257ce647f04b111de71863sewardj 231079048ce723a3463c70257ce647f04b111de71863sewardj 231145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 231245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 231345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Handling mappings which do not arise directly from the ---*/ 231445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- simulation of the client. ---*/ 231545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 231645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 231779048ce723a3463c70257ce647f04b111de71863sewardj 231845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- --- map, unmap, protect --- --- --- */ 231979048ce723a3463c70257ce647f04b111de71863sewardj 232045f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map a file at a fixed address for the client, and update the 232145f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment array accordingly. */ 232279048ce723a3463c70257ce647f04b111de71863sewardj 232345f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_file_fixed_client) 2324274461dcb67f680196c97e8afb7028a79b97dcb7sewardj ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset ) 232545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 23268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj UInt flags = VKI_MAP_FIXED | VKI_MAP_PRIVATE; 23278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return VG_(am_mmap_named_file_fixed_client_flags)(start, length, prot, flags, 23288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj fd, offset, NULL); 23298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 23308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 23318eb8bab992e3998c33770b0cdb16059a8b918a06sewardjSysRes VG_(am_mmap_file_fixed_client_flags) 23328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ( Addr start, SizeT length, UInt prot, UInt flags, Int fd, Off64T offset ) 23338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 23348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return VG_(am_mmap_named_file_fixed_client_flags)(start, length, prot, flags, 23358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj fd, offset, NULL); 2336f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 2337f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2338f76d27a697a7b0bf3b84490baf60623fc96a23afnjnSysRes VG_(am_mmap_named_file_fixed_client) 2339f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset, const HChar *name ) 2340f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 23418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj UInt flags = VKI_MAP_FIXED | VKI_MAP_PRIVATE; 23428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return VG_(am_mmap_named_file_fixed_client_flags)(start, length, prot, flags, 23438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj fd, offset, name); 23448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 23458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 23468eb8bab992e3998c33770b0cdb16059a8b918a06sewardjSysRes VG_(am_mmap_named_file_fixed_client_flags) 23478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ( Addr start, SizeT length, UInt prot, UInt flags, 23488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Int fd, Off64T offset, const HChar *name ) 23498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 235045f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 235145f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 235245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr advised; 235345f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool ok; 235445f4e7c91119c7d01a59f5e827c67841632c9314sewardj MapRequest req; 2355419060073e7943846cc9e0bcdcb25258d90da2dcsewardj ULong dev, ino; 2356f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom UInt mode; 235745f4e7c91119c7d01a59f5e827c67841632c9314sewardj HChar buf[VKI_PATH_MAX]; 235845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 235945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Not allowable. */ 2360274461dcb67f680196c97e8afb7028a79b97dcb7sewardj if (length == 0 2361274461dcb67f680196c97e8afb7028a79b97dcb7sewardj || !VG_IS_PAGE_ALIGNED(start) 2362274461dcb67f680196c97e8afb7028a79b97dcb7sewardj || !VG_IS_PAGE_ALIGNED(offset)) 236345f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 236445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 236545f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ask for an advisory. If it's negative, fail immediately. */ 236645f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.rkind = MFixed; 236745f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.start = start; 236845f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.len = length; 2369515e26933c61eed21ba8d74ecdfc89c217832fedphilippe advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok ); 237045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!ok || advised != start) 237145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 237245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 237345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* We have been advised that the mapping is allowable at the 237445f4e7c91119c7d01a59f5e827c67841632c9314sewardj specified address. So hand it off to the kernel, and propagate 237545f4e7c91119c7d01a59f5e827c67841632c9314sewardj any resulting failure immediately. */ 2376f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 237745f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 23788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj start, length, prot, flags, 237945f4e7c91119c7d01a59f5e827c67841632c9314sewardj fd, offset 238045f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 2381cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 238245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 238345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2384cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != start) { 238545f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* I don't think this can happen. It means the kernel made a 238645f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixed map succeed but not at the requested location. Try to 238745f4e7c91119c7d01a59f5e827c67841632c9314sewardj repair the damage, then return saying the mapping failed. */ 2388cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 238945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 239079048ce723a3463c70257ce647f04b111de71863sewardj } 239179048ce723a3463c70257ce647f04b111de71863sewardj 239245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, the mapping succeeded. Now notify the interval map. */ 239345f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 239445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkFileC; 239545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = start; 239645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = seg.start + VG_PGROUNDUP(length) - 1; 239745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.offset = offset; 239845f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = toBool(prot & VKI_PROT_READ); 239945f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = toBool(prot & VKI_PROT_WRITE); 240045f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = toBool(prot & VKI_PROT_EXEC); 2401dad944add53e6361751c6832066c00c456854622njn if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { 240245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.dev = dev; 240345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.ino = ino; 2404f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom seg.mode = mode; 240579048ce723a3463c70257ce647f04b111de71863sewardj } 2406f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (name) { 24074ecd48360351f666f008148c12a24cbda455c6b1florian seg.fnIdx = ML_(am_allocate_segname)( name ); 2408f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { 24094ecd48360351f666f008148c12a24cbda455c6b1florian seg.fnIdx = ML_(am_allocate_segname)( buf ); 241079048ce723a3463c70257ce647f04b111de71863sewardj } 241145f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 241279048ce723a3463c70257ce647f04b111de71863sewardj 241345f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 241445f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 241579048ce723a3463c70257ce647f04b111de71863sewardj} 241679048ce723a3463c70257ce647f04b111de71863sewardj 241779048ce723a3463c70257ce647f04b111de71863sewardj 241845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map anonymously at a fixed address for the client, and update 241945f4e7c91119c7d01a59f5e827c67841632c9314sewardj the segment array accordingly. */ 2420de4a1d01951937632098a6cda45859afa587a06fsewardj 242145f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_anon_fixed_client) ( Addr start, SizeT length, UInt prot ) 242298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge{ 242345f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 242445f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 242545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr advised; 242645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool ok; 242745f4e7c91119c7d01a59f5e827c67841632c9314sewardj MapRequest req; 242845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 242945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Not allowable. */ 243045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (length == 0 || !VG_IS_PAGE_ALIGNED(start)) 243145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 243245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 243345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ask for an advisory. If it's negative, fail immediately. */ 243445f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.rkind = MFixed; 243545f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.start = start; 243645f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.len = length; 2437515e26933c61eed21ba8d74ecdfc89c217832fedphilippe advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok ); 243845f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!ok || advised != start) 243945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 244045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 244145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* We have been advised that the mapping is allowable at the 244245f4e7c91119c7d01a59f5e827c67841632c9314sewardj specified address. So hand it off to the kernel, and propagate 244345f4e7c91119c7d01a59f5e827c67841632c9314sewardj any resulting failure immediately. */ 2444f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 244545f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 244645f4e7c91119c7d01a59f5e827c67841632c9314sewardj start, length, prot, 244745f4e7c91119c7d01a59f5e827c67841632c9314sewardj VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 244845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 0, 0 244945f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 2450cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 245145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 245245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2453cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != start) { 245445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* I don't think this can happen. It means the kernel made a 245545f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixed map succeed but not at the requested location. Try to 245645f4e7c91119c7d01a59f5e827c67841632c9314sewardj repair the damage, then return saying the mapping failed. */ 2457cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 245845f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 245945f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 246098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 246145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, the mapping succeeded. Now notify the interval map. */ 246245f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 246345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkAnonC; 246445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = start; 246545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = seg.start + VG_PGROUNDUP(length) - 1; 246645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = toBool(prot & VKI_PROT_READ); 246745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = toBool(prot & VKI_PROT_WRITE); 246845f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = toBool(prot & VKI_PROT_EXEC); 246945f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 247045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 247145f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 247245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 247398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge} 247498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 247598abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 247645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map anonymously at an unconstrained address for the client, and 247745f4e7c91119c7d01a59f5e827c67841632c9314sewardj update the segment array accordingly. */ 247898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 247945f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot ) 248098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge{ 248145f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 248245f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 248345f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr advised; 248445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool ok; 248545f4e7c91119c7d01a59f5e827c67841632c9314sewardj MapRequest req; 248645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 248745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Not allowable. */ 248845f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (length == 0) 248945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 249045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 249145f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ask for an advisory. If it's negative, fail immediately. */ 249245f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.rkind = MAny; 249345f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.start = 0; 249445f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.len = length; 2495515e26933c61eed21ba8d74ecdfc89c217832fedphilippe advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok ); 249645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!ok) 249745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 249845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 249945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* We have been advised that the mapping is allowable at the 250045f4e7c91119c7d01a59f5e827c67841632c9314sewardj advised address. So hand it off to the kernel, and propagate 250145f4e7c91119c7d01a59f5e827c67841632c9314sewardj any resulting failure immediately. */ 2502f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 250345f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 250445f4e7c91119c7d01a59f5e827c67841632c9314sewardj advised, length, prot, 250545f4e7c91119c7d01a59f5e827c67841632c9314sewardj VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 250645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 0, 0 250745f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 2508cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 250945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 251045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2511cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != advised) { 251245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* I don't think this can happen. It means the kernel made a 251345f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixed map succeed but not at the requested location. Try to 251445f4e7c91119c7d01a59f5e827c67841632c9314sewardj repair the damage, then return saying the mapping failed. */ 2515cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 251645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2517e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn } 251845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 251945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, the mapping succeeded. Now notify the interval map. */ 252045f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 252145f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkAnonC; 252245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = advised; 252345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = seg.start + VG_PGROUNDUP(length) - 1; 252445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = toBool(prot & VKI_PROT_READ); 252545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = toBool(prot & VKI_PROT_WRITE); 252645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = toBool(prot & VKI_PROT_EXEC); 252745f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 252845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 252945f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 253045f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 253198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge} 253298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 253345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 253445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map anonymously at an unconstrained address for V, and update the 253545f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment array accordingly. This is fundamentally how V allocates 253645f4e7c91119c7d01a59f5e827c67841632c9314sewardj itself more address space when needed. */ 253745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 253845f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) 25391024cf78e01e14eaa19ed6a8cd11beb50e6bc687sewardj{ 254045f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 254145f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 254245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr advised; 254345f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool ok; 254445f4e7c91119c7d01a59f5e827c67841632c9314sewardj MapRequest req; 254545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 254645f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Not allowable. */ 254745f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (length == 0) 254845f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 254945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 255045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ask for an advisory. If it's negative, fail immediately. */ 255145f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.rkind = MAny; 255245f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.start = 0; 255345f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.len = length; 2554515e26933c61eed21ba8d74ecdfc89c217832fedphilippe advised = VG_(am_get_advisory)( &req, False/*forClient*/, &ok ); 255545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!ok) 255645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 255745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2558f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// On Darwin, for anonymous maps you can pass in a tag which is used by 2559f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// programs like vmmap for statistical purposes. 2560f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#ifndef VM_TAG_VALGRIND 2561f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# define VM_TAG_VALGRIND 0 2562f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 2563f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 256445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* We have been advised that the mapping is allowable at the 256545f4e7c91119c7d01a59f5e827c67841632c9314sewardj specified address. So hand it off to the kernel, and propagate 256645f4e7c91119c7d01a59f5e827c67841632c9314sewardj any resulting failure immediately. */ 2567f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* GrP fixme darwin: use advisory as a hint only, otherwise syscall in 2568f76d27a697a7b0bf3b84490baf60623fc96a23afnjn another thread can pre-empt our spot. [At one point on the DARWIN 2569f76d27a697a7b0bf3b84490baf60623fc96a23afnjn branch the VKI_MAP_FIXED was commented out; unclear if this is 2570f76d27a697a7b0bf3b84490baf60623fc96a23afnjn necessary or not given the second Darwin-only call that immediately 25713bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe follows if this one fails. --njn] 25723bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe Also, an inner valgrind cannot observe the mmap syscalls done by 25733bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe the outer valgrind. The outer Valgrind might make the mmap 25743bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe fail here, as the inner valgrind believes that a segment is free, 25753bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe while it is in fact used by the outer valgrind. 25763bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe So, for an inner valgrind, similarly to DARWIN, if the fixed mmap 25773bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe fails, retry the mmap without map fixed. 25783bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe This is a kludge which on linux is only activated for the inner. 25793bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe The state of the inner aspacemgr is not made correct by this kludge 25803bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe and so a.o. VG_(am_do_sync_check) could fail. 25813bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe A proper solution implies a better collaboration between the 25823bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe inner and the outer (e.g. inner VG_(am_get_advisory) should do 25833bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe a client request to call the outer VG_(am_get_advisory). */ 258445f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 258545f4e7c91119c7d01a59f5e827c67841632c9314sewardj advised, length, 258645f4e7c91119c7d01a59f5e827c67841632c9314sewardj VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 258745f4e7c91119c7d01a59f5e827c67841632c9314sewardj VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2588f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VM_TAG_VALGRIND, 0 258945f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 25903bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe#if defined(VGO_darwin) || defined(ENABLE_INNER) 25913bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe /* Kludge on Darwin and inner linux if the fixed mmap failed. */ 2592f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (sr_isError(sres)) { 2593f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* try again, ignoring the advisory */ 2594f76d27a697a7b0bf3b84490baf60623fc96a23afnjn sres = VG_(am_do_mmap_NO_NOTIFY)( 2595f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 0, length, 2596f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 2597f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /*VKI_MAP_FIXED|*/VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2598f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VM_TAG_VALGRIND, 0 2599f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ); 2600f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 2601f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 2602cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 260345f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 260445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 26053bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe#if defined(VGO_linux) && !defined(ENABLE_INNER) 26063bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe /* Doing the check only in linux not inner, as the below 26073bf117dd6e0ab3bec8eedd36da9d9602bb82c542philippe check can fail when the kludge above has been used. */ 2608cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != advised) { 260945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* I don't think this can happen. It means the kernel made a 261045f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixed map succeed but not at the requested location. Try to 261145f4e7c91119c7d01a59f5e827c67841632c9314sewardj repair the damage, then return saying the mapping failed. */ 2612cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 261345f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 26141024cf78e01e14eaa19ed6a8cd11beb50e6bc687sewardj } 2615f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif 261645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 261745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, the mapping succeeded. Now notify the interval map. */ 261845f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 261945f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkAnonV; 2620cda2f0fbda4c4b2644babc830244be8aed95de1dnjn seg.start = sr_Res(sres); 262145f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = seg.start + VG_PGROUNDUP(length) - 1; 262245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = True; 262345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = True; 262445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = True; 262545f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 262645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 262745f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 262845f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 262998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge} 263098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 263145f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Really just a wrapper around VG_(am_mmap_anon_float_valgrind). */ 26321024cf78e01e14eaa19ed6a8cd11beb50e6bc687sewardj 263345f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid* VG_(am_shadow_alloc)(SizeT size) 263498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge{ 263545f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres = VG_(am_mmap_anon_float_valgrind)( size ); 2636cda2f0fbda4c4b2644babc830244be8aed95de1dnjn return sr_isError(sres) ? NULL : (void*)sr_Res(sres); 263745f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 263898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 263945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Map a file at an unconstrained address for V, and update the 26403b290486cd4cd601b20e04340e593c9ed9717e5fsewardj segment array accordingly. Use the provided flags */ 264198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 26423b290486cd4cd601b20e04340e593c9ed9717e5fsewardjstatic SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot, 26433b290486cd4cd601b20e04340e593c9ed9717e5fsewardj UInt flags, 26443b290486cd4cd601b20e04340e593c9ed9717e5fsewardj Int fd, Off64T offset ) 264545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 264645f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 264745f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 264845f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr advised; 264945f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool ok; 265045f4e7c91119c7d01a59f5e827c67841632c9314sewardj MapRequest req; 2651419060073e7943846cc9e0bcdcb25258d90da2dcsewardj ULong dev, ino; 2652f4c231081a5c8ff6f24b3fa1980349199f1d9ea3tom UInt mode; 265345f4e7c91119c7d01a59f5e827c67841632c9314sewardj HChar buf[VKI_PATH_MAX]; 265445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 265545f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Not allowable. */ 2656274461dcb67f680196c97e8afb7028a79b97dcb7sewardj if (length == 0 || !VG_IS_PAGE_ALIGNED(offset)) 265745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 265845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 265945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ask for an advisory. If it's negative, fail immediately. */ 266045f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.rkind = MAny; 266145f4e7c91119c7d01a59f5e827c67841632c9314sewardj req.start = 0; 26620eb0d5a73655b8ed1b6c93d7032311a5d102a8f0philippe #if defined(VGA_arm) || defined(VGA_arm64) \ 26630eb0d5a73655b8ed1b6c93d7032311a5d102a8f0philippe || defined(VGA_mips32) || defined(VGA_mips64) 266453b0d9a5e90ecd4e4b50489915c221c86734908fphilippe aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE); 266553b0d9a5e90ecd4e4b50489915c221c86734908fphilippe #else 266653b0d9a5e90ecd4e4b50489915c221c86734908fphilippe aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE); 266753b0d9a5e90ecd4e4b50489915c221c86734908fphilippe #endif 266853b0d9a5e90ecd4e4b50489915c221c86734908fphilippe if ((VKI_SHMLBA > VKI_PAGE_SIZE) && (VKI_MAP_SHARED & flags)) { 266953b0d9a5e90ecd4e4b50489915c221c86734908fphilippe /* arm-linux only. See ML_(generic_PRE_sys_shmat) and bug 290974 */ 267053b0d9a5e90ecd4e4b50489915c221c86734908fphilippe req.len = length + VKI_SHMLBA - VKI_PAGE_SIZE; 267153b0d9a5e90ecd4e4b50489915c221c86734908fphilippe } else { 267253b0d9a5e90ecd4e4b50489915c221c86734908fphilippe req.len = length; 267353b0d9a5e90ecd4e4b50489915c221c86734908fphilippe } 2674515e26933c61eed21ba8d74ecdfc89c217832fedphilippe advised = VG_(am_get_advisory)( &req, False/*forClient*/, &ok ); 267545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!ok) 267645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 267753b0d9a5e90ecd4e4b50489915c221c86734908fphilippe if ((VKI_SHMLBA > VKI_PAGE_SIZE) && (VKI_MAP_SHARED & flags)) 267853b0d9a5e90ecd4e4b50489915c221c86734908fphilippe advised = VG_ROUNDUP(advised, VKI_SHMLBA); 267945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 268045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* We have been advised that the mapping is allowable at the 268145f4e7c91119c7d01a59f5e827c67841632c9314sewardj specified address. So hand it off to the kernel, and propagate 268245f4e7c91119c7d01a59f5e827c67841632c9314sewardj any resulting failure immediately. */ 268345f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 268445f4e7c91119c7d01a59f5e827c67841632c9314sewardj advised, length, prot, 26853b290486cd4cd601b20e04340e593c9ed9717e5fsewardj flags, 268645f4e7c91119c7d01a59f5e827c67841632c9314sewardj fd, offset 268745f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 2688cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 268945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 269045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2691cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != advised) { 269245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* I don't think this can happen. It means the kernel made a 269345f4e7c91119c7d01a59f5e827c67841632c9314sewardj fixed map succeed but not at the requested location. Try to 269445f4e7c91119c7d01a59f5e827c67841632c9314sewardj repair the damage, then return saying the mapping failed. */ 2695cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 269645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 269745f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 269898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 269945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, the mapping succeeded. Now notify the interval map. */ 270045f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 270145f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkFileV; 2702cda2f0fbda4c4b2644babc830244be8aed95de1dnjn seg.start = sr_Res(sres); 270345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = seg.start + VG_PGROUNDUP(length) - 1; 270445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.offset = offset; 270545f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasR = toBool(prot & VKI_PROT_READ); 270645f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasW = toBool(prot & VKI_PROT_WRITE); 270745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.hasX = toBool(prot & VKI_PROT_EXEC); 2708dad944add53e6361751c6832066c00c456854622njn if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { 2709cf4ac71eeefa63bb2edc6b9ed09584612a3a7db0sewardj seg.dev = dev; 2710cf4ac71eeefa63bb2edc6b9ed09584612a3a7db0sewardj seg.ino = ino; 2711cf4ac71eeefa63bb2edc6b9ed09584612a3a7db0sewardj seg.mode = mode; 271245f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 2713dad944add53e6361751c6832066c00c456854622njn if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { 27144ecd48360351f666f008148c12a24cbda455c6b1florian seg.fnIdx = ML_(am_allocate_segname)( buf ); 271545f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 271645f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 271747c98a767e79e36511bf7b177a5b5d24930efd7csewardj 271845f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 271945f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 272045f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 27213b290486cd4cd601b20e04340e593c9ed9717e5fsewardj/* Map privately a file at an unconstrained address for V, and update the 27223b290486cd4cd601b20e04340e593c9ed9717e5fsewardj segment array accordingly. This is used by V for transiently 27233b290486cd4cd601b20e04340e593c9ed9717e5fsewardj mapping in object files to read their debug info. */ 27243b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 27253b290486cd4cd601b20e04340e593c9ed9717e5fsewardjSysRes VG_(am_mmap_file_float_valgrind) ( SizeT length, UInt prot, 27263b290486cd4cd601b20e04340e593c9ed9717e5fsewardj Int fd, Off64T offset ) 27273b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{ 27283b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return VG_(am_mmap_file_float_valgrind_flags) (length, prot, 27293b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VKI_MAP_FIXED|VKI_MAP_PRIVATE, 27303b290486cd4cd601b20e04340e593c9ed9717e5fsewardj fd, offset ); 27313b290486cd4cd601b20e04340e593c9ed9717e5fsewardj} 273247c98a767e79e36511bf7b177a5b5d24930efd7csewardj 2733d6633333a292fc9b64f04200d836b08f55889321sewardjSysRes VG_(am_shared_mmap_file_float_valgrind) 27343b290486cd4cd601b20e04340e593c9ed9717e5fsewardj ( SizeT length, UInt prot, Int fd, Off64T offset ) 27353b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{ 27363b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return VG_(am_mmap_file_float_valgrind_flags) (length, prot, 27373b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VKI_MAP_FIXED|VKI_MAP_SHARED, 27383b290486cd4cd601b20e04340e593c9ed9717e5fsewardj fd, offset ); 27393b290486cd4cd601b20e04340e593c9ed9717e5fsewardj} 274098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 27412fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian/* Convenience wrapper around VG_(am_mmap_anon_float_client) which also 27422fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian marks the segment as containing the client heap. This is for the benefit 27432fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian of the leak checker which needs to be able to identify such segments 27442fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian so as not to use them as sources of roots during leak checks. */ 27452fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorianSysRes VG_(am_mmap_client_heap) ( SizeT length, Int prot ) 27462fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian{ 27472fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian SysRes res = VG_(am_mmap_anon_float_client)(length, prot); 27482fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian 27492fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian if (! sr_isError(res)) { 27502fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian Addr addr = sr_Res(res); 27512fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian Int ix = find_nsegment_idx(addr); 27522fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian 27532fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian nsegments[ix].isCH = True; 27542fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian } 27552fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian return res; 27562fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian} 27572fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian 275845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- munmap helper --- --- */ 275998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 276045f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic 276145f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes am_munmap_both_wrk ( /*OUT*/Bool* need_discard, 276245f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr start, SizeT len, Bool forClient ) 276345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 276445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool d; 276545f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 276698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 276745f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!VG_IS_PAGE_ALIGNED(start)) 276845f4e7c91119c7d01a59f5e827c67841632c9314sewardj goto eINVAL; 276947c98a767e79e36511bf7b177a5b5d24930efd7csewardj 277045f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (len == 0) { 277145f4e7c91119c7d01a59f5e827c67841632c9314sewardj *need_discard = False; 277245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Success)( 0 ); 2773e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn } 277498abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 277545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (start + len < len) 277645f4e7c91119c7d01a59f5e827c67841632c9314sewardj goto eINVAL; 2777a8d8e239876796bc194636b8bb4b3b3c86db8528sewardj 277813bfd85dfab2cd301c92e308b274ebd17de830d2njn len = VG_PGROUNDUP(len); 277945f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 278045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 278198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 278245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (forClient) { 278345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!VG_(am_is_valid_for_client_or_free_or_resvn) 278445f4e7c91119c7d01a59f5e827c67841632c9314sewardj ( start, len, VKI_PROT_NONE )) 278545f4e7c91119c7d01a59f5e827c67841632c9314sewardj goto eINVAL; 278645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else { 2787adfff76735ea5bca870dec8f382b225728e1b32dphilippe if (!VG_(am_is_valid_for_valgrind) 2788adfff76735ea5bca870dec8f382b225728e1b32dphilippe ( start, len, VKI_PROT_NONE )) 278945f4e7c91119c7d01a59f5e827c67841632c9314sewardj goto eINVAL; 279098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge } 279198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 279245f4e7c91119c7d01a59f5e827c67841632c9314sewardj d = any_Ts_in_range( start, len ); 279398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 2794297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj sres = ML_(am_do_munmap_NO_NOTIFY)( start, len ); 2795cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 279645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 279798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 279845f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(am_notify_munmap)( start, len ); 279945f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 280045f4e7c91119c7d01a59f5e827c67841632c9314sewardj *need_discard = d; 280145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return sres; 280298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 280345f4e7c91119c7d01a59f5e827c67841632c9314sewardj eINVAL: 280445f4e7c91119c7d01a59f5e827c67841632c9314sewardj return VG_(mk_SysRes_Error)( VKI_EINVAL ); 280545f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 280698abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 280745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Unmap the given address range and update the segment array 280845f4e7c91119c7d01a59f5e827c67841632c9314sewardj accordingly. This fails if the range isn't valid for the client. 280945f4e7c91119c7d01a59f5e827c67841632c9314sewardj If *need_discard is True after a successful return, the caller 281045f4e7c91119c7d01a59f5e827c67841632c9314sewardj should immediately discard translations from the specified address 281145f4e7c91119c7d01a59f5e827c67841632c9314sewardj range. */ 281298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 281345f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard, 281445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr start, SizeT len ) 281545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 281645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return am_munmap_both_wrk( need_discard, start, len, True/*client*/ ); 2817de4a1d01951937632098a6cda45859afa587a06fsewardj} 2818de4a1d01951937632098a6cda45859afa587a06fsewardj 281945f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Unmap the given address range and update the segment array 282045f4e7c91119c7d01a59f5e827c67841632c9314sewardj accordingly. This fails if the range isn't valid for valgrind. */ 2821de4a1d01951937632098a6cda45859afa587a06fsewardj 282245f4e7c91119c7d01a59f5e827c67841632c9314sewardjSysRes VG_(am_munmap_valgrind)( Addr start, SizeT len ) 282345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 282445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Bool need_discard; 282545f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes r = am_munmap_both_wrk( &need_discard, 282645f4e7c91119c7d01a59f5e827c67841632c9314sewardj start, len, False/*valgrind*/ ); 282745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* If this assertion fails, it means we allowed translations to be 282845f4e7c91119c7d01a59f5e827c67841632c9314sewardj made from a V-owned section. Which shouldn't happen. */ 2829cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (!sr_isError(r)) 283045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(!need_discard); 283145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return r; 283298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge} 283398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 283445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Let (start,len) denote an area within a single Valgrind-owned 283545f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment (anon or file). Change the ownership of [start, start+len) 283645f4e7c91119c7d01a59f5e827c67841632c9314sewardj to the client instead. Fails if (start,len) does not denote a 283745f4e7c91119c7d01a59f5e827c67841632c9314sewardj suitable segment. */ 283845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 283945f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len ) 2840de4a1d01951937632098a6cda45859afa587a06fsewardj{ 284145f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int i, iLo, iHi; 2842de4a1d01951937632098a6cda45859afa587a06fsewardj 284345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (len == 0) 284445f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; 284545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (start + len < start) 284645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 284745f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!VG_IS_PAGE_ALIGNED(start) || !VG_IS_PAGE_ALIGNED(len)) 284845f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 2849e517b80ab9ac4da3544fdb905ce76fcabf92da97sewardj 285045f4e7c91119c7d01a59f5e827c67841632c9314sewardj i = find_nsegment_idx(start); 285145f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[i].kind != SkFileV && nsegments[i].kind != SkAnonV) 285245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 285345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (start+len-1 > nsegments[i].end) 285445f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 285598abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 285645f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(start >= nsegments[i].start); 285745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(start+len-1 <= nsegments[i].end); 285845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 285945f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* This scheme is like how mprotect works: split the to-be-changed 286045f4e7c91119c7d01a59f5e827c67841632c9314sewardj range into its own segment(s), then mess with them (it). There 286145f4e7c91119c7d01a59f5e827c67841632c9314sewardj should be only one. */ 286245f4e7c91119c7d01a59f5e827c67841632c9314sewardj split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi ); 286345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(iLo == iHi); 286445f4e7c91119c7d01a59f5e827c67841632c9314sewardj switch (nsegments[iLo].kind) { 286545f4e7c91119c7d01a59f5e827c67841632c9314sewardj case SkFileV: nsegments[iLo].kind = SkFileC; break; 286645f4e7c91119c7d01a59f5e827c67841632c9314sewardj case SkAnonV: nsegments[iLo].kind = SkAnonC; break; 286745f4e7c91119c7d01a59f5e827c67841632c9314sewardj default: aspacem_assert(0); /* can't happen - guarded above */ 286845f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 286998abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 287045f4e7c91119c7d01a59f5e827c67841632c9314sewardj preen_nsegments(); 287145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; 287245f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 2873548be6d64c58729588a559b1512ad7625bc1b86esewardj 28742fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian/* Set the 'hasT' bit on the segment containing ADDR indicating that 28752fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian translations have or may have been taken from this segment. ADDR is 28762fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian expected to belong to a client segment. */ 28772fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorianvoid VG_(am_set_segment_hasT)( Addr addr ) 2878716f31ac50be6070a96b490d0b0bbd39b8e77342sewardj{ 28792fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian Int i = find_nsegment_idx(addr); 28802fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian SegKind kind = nsegments[i].kind; 28812fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian aspacem_assert(kind == SkAnonC || kind == SkFileC || kind == SkShmC); 28822fa66ce8abeb95c722dcbd5bd233a26288f2cd7dflorian nsegments[i].hasT = True; 2883716f31ac50be6070a96b490d0b0bbd39b8e77342sewardj} 2884716f31ac50be6070a96b490d0b0bbd39b8e77342sewardj 288598abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 288645f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- --- reservations --- --- --- */ 2887de4a1d01951937632098a6cda45859afa587a06fsewardj 288845f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Create a reservation from START .. START+LENGTH-1, with the given 288945f4e7c91119c7d01a59f5e827c67841632c9314sewardj ShrinkMode. When checking whether the reservation can be created, 289045f4e7c91119c7d01a59f5e827c67841632c9314sewardj also ensure that at least abs(EXTRA) extra free bytes will remain 289145f4e7c91119c7d01a59f5e827c67841632c9314sewardj above (> 0) or below (< 0) the reservation. 289298abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 289345f4e7c91119c7d01a59f5e827c67841632c9314sewardj The reservation will only be created if it, plus the extra-zone, 289445f4e7c91119c7d01a59f5e827c67841632c9314sewardj falls entirely within a single free segment. The returned Bool 289545f4e7c91119c7d01a59f5e827c67841632c9314sewardj indicates whether the creation succeeded. */ 289679048ce723a3463c70257ce647f04b111de71863sewardj 289745f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_create_reservation) ( Addr start, SizeT length, 289845f4e7c91119c7d01a59f5e827c67841632c9314sewardj ShrinkMode smode, SSizeT extra ) 289945f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 290045f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int startI, endI; 290145f4e7c91119c7d01a59f5e827c67841632c9314sewardj NSegment seg; 2902e517b80ab9ac4da3544fdb905ce76fcabf92da97sewardj 290345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* start and end, not taking into account the extra space. */ 290445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr start1 = start; 290545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr end1 = start + length - 1; 2906e517b80ab9ac4da3544fdb905ce76fcabf92da97sewardj 290745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* start and end, taking into account the extra space. */ 290845f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr start2 = start1; 290945f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr end2 = end1; 291098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 291145f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (extra < 0) start2 += extra; // this moves it down :-) 291245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (extra > 0) end2 += extra; 291398abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 291445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 291545f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start+length)); 291645f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(start2)); 291745f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(end2+1)); 291898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 291945f4e7c91119c7d01a59f5e827c67841632c9314sewardj startI = find_nsegment_idx( start2 ); 292045f4e7c91119c7d01a59f5e827c67841632c9314sewardj endI = find_nsegment_idx( end2 ); 2921548be6d64c58729588a559b1512ad7625bc1b86esewardj 292245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* If the start and end points don't fall within the same (free) 292345f4e7c91119c7d01a59f5e827c67841632c9314sewardj segment, we're hosed. This does rely on the assumption that all 292445f4e7c91119c7d01a59f5e827c67841632c9314sewardj mergeable adjacent segments can be merged, but add_segment() 292545f4e7c91119c7d01a59f5e827c67841632c9314sewardj should ensure that. */ 292645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (startI != endI) 292745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 2928548be6d64c58729588a559b1512ad7625bc1b86esewardj 292945f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (nsegments[startI].kind != SkFree) 293045f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 2931548be6d64c58729588a559b1512ad7625bc1b86esewardj 293245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Looks good - make the reservation. */ 293345f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(nsegments[startI].start <= start2); 293445f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(end2 <= nsegments[startI].end); 2935548be6d64c58729588a559b1512ad7625bc1b86esewardj 293645f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 293745f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.kind = SkResvn; 293845f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = start1; /* NB: extra space is not included in the 293945f4e7c91119c7d01a59f5e827c67841632c9314sewardj reservation. */ 294045f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = end1; 294145f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.smode = smode; 294245f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 2943548be6d64c58729588a559b1512ad7625bc1b86esewardj 294445f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 294545f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; 294645f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 2947548be6d64c58729588a559b1512ad7625bc1b86esewardj 2948548be6d64c58729588a559b1512ad7625bc1b86esewardj 2949888b8159535580b30550f99cb7361f62edd83100florian/* ADDR is the start address of an anonymous client mapping. This fn extends 2950888b8159535580b30550f99cb7361f62edd83100florian the mapping by DELTA bytes, taking the space from a reservation section 295145f4e7c91119c7d01a59f5e827c67841632c9314sewardj which must be adjacent. If DELTA is positive, the segment is 295245f4e7c91119c7d01a59f5e827c67841632c9314sewardj extended forwards in the address space, and the reservation must be 295345f4e7c91119c7d01a59f5e827c67841632c9314sewardj the next one along. If DELTA is negative, the segment is extended 295445f4e7c91119c7d01a59f5e827c67841632c9314sewardj backwards in the address space and the reservation must be the 29556684d2afc25363b29a9ce4281050161d91baeebfsewardj previous one. DELTA must be page aligned. abs(DELTA) must not 29566684d2afc25363b29a9ce4281050161d91baeebfsewardj exceed the size of the reservation segment minus one page, that is, 29576684d2afc25363b29a9ce4281050161d91baeebfsewardj the reservation segment after the operation must be at least one 2958888b8159535580b30550f99cb7361f62edd83100florian page long. The function returns a pointer to the resized segment. */ 2959548be6d64c58729588a559b1512ad7625bc1b86esewardj 2960888b8159535580b30550f99cb7361f62edd83100florianconst NSegment *VG_(am_extend_into_adjacent_reservation_client)( Addr addr, 296115fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian SSizeT delta, 296215fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian Bool *overflow) 296345f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 296445f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int segA, segR; 296545f4e7c91119c7d01a59f5e827c67841632c9314sewardj UInt prot; 296645f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 2967548be6d64c58729588a559b1512ad7625bc1b86esewardj 296815fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian *overflow = False; 296915fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian 2970888b8159535580b30550f99cb7361f62edd83100florian segA = find_nsegment_idx(addr); 2971888b8159535580b30550f99cb7361f62edd83100florian aspacem_assert(nsegments[segA].kind == SkAnonC); 297245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 297345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (delta == 0) 2974888b8159535580b30550f99cb7361f62edd83100florian return nsegments + segA; 297545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 297645f4e7c91119c7d01a59f5e827c67841632c9314sewardj prot = (nsegments[segA].hasR ? VKI_PROT_READ : 0) 297745f4e7c91119c7d01a59f5e827c67841632c9314sewardj | (nsegments[segA].hasW ? VKI_PROT_WRITE : 0) 297845f4e7c91119c7d01a59f5e827c67841632c9314sewardj | (nsegments[segA].hasX ? VKI_PROT_EXEC : 0); 297945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 298045f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(VG_IS_PAGE_ALIGNED(delta<0 ? -delta : delta)); 298145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 298245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (delta > 0) { 298345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 298445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Extending the segment forwards. */ 298545f4e7c91119c7d01a59f5e827c67841632c9314sewardj segR = segA+1; 298645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (segR >= nsegments_used 298745f4e7c91119c7d01a59f5e827c67841632c9314sewardj || nsegments[segR].kind != SkResvn 298815fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian || nsegments[segR].smode != SmLower) 298915fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian return NULL; 299015fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian 299115fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian if (delta + VKI_PAGE_SIZE 299215fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian > (nsegments[segR].end - nsegments[segR].start + 1)) { 299315fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian *overflow = True; 299415fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian return NULL; 299515fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian } 299645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 299745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Extend the kernel's mapping. */ 2998f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 299945f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 300045f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[segR].start, delta, 300145f4e7c91119c7d01a59f5e827c67841632c9314sewardj prot, 300245f4e7c91119c7d01a59f5e827c67841632c9314sewardj VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 300345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 0, 0 300445f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 3005cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 3006888b8159535580b30550f99cb7361f62edd83100florian return NULL; /* kernel bug if this happens? */ 3007cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != nsegments[segR].start) { 300845f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* kernel bug if this happens? */ 3009cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta ); 3010888b8159535580b30550f99cb7361f62edd83100florian return NULL; 3011548be6d64c58729588a559b1512ad7625bc1b86esewardj } 3012548be6d64c58729588a559b1512ad7625bc1b86esewardj 301345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, success with the kernel. Update our structures. */ 30143bfb914e76943b35e96bbaead678c2c96f3380edflorian nsegments[segR].start += delta; 30153bfb914e76943b35e96bbaead678c2c96f3380edflorian nsegments[segA].end += delta; 30163bfb914e76943b35e96bbaead678c2c96f3380edflorian aspacem_assert(nsegments[segR].start <= nsegments[segR].end); 3017548be6d64c58729588a559b1512ad7625bc1b86esewardj 3018548be6d64c58729588a559b1512ad7625bc1b86esewardj } else { 3019548be6d64c58729588a559b1512ad7625bc1b86esewardj 302045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Extending the segment backwards. */ 302145f4e7c91119c7d01a59f5e827c67841632c9314sewardj delta = -delta; 302245f4e7c91119c7d01a59f5e827c67841632c9314sewardj aspacem_assert(delta > 0); 302345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 302445f4e7c91119c7d01a59f5e827c67841632c9314sewardj segR = segA-1; 302545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (segR < 0 302645f4e7c91119c7d01a59f5e827c67841632c9314sewardj || nsegments[segR].kind != SkResvn 302715fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian || nsegments[segR].smode != SmUpper) 302815fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian return NULL; 302915fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian 303015fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian if (delta + VKI_PAGE_SIZE 303115fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian > (nsegments[segR].end - nsegments[segR].start + 1)) { 303215fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian *overflow = True; 303315fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian return NULL; 303415fa8a2f9b64e24c76ef88d8bf660ea2296f0c36florian } 303545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 303645f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Extend the kernel's mapping. */ 3037f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 303845f4e7c91119c7d01a59f5e827c67841632c9314sewardj sres = VG_(am_do_mmap_NO_NOTIFY)( 303945f4e7c91119c7d01a59f5e827c67841632c9314sewardj nsegments[segA].start-delta, delta, 304045f4e7c91119c7d01a59f5e827c67841632c9314sewardj prot, 304145f4e7c91119c7d01a59f5e827c67841632c9314sewardj VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 304245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 0, 0 304345f4e7c91119c7d01a59f5e827c67841632c9314sewardj ); 3044cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) 3045888b8159535580b30550f99cb7361f62edd83100florian return NULL; /* kernel bug if this happens? */ 3046cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_Res(sres) != nsegments[segA].start-delta) { 304745f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* kernel bug if this happens? */ 3048cda2f0fbda4c4b2644babc830244be8aed95de1dnjn (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta ); 3049888b8159535580b30550f99cb7361f62edd83100florian return NULL; 305045f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 3051548be6d64c58729588a559b1512ad7625bc1b86esewardj 305245f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Ok, success with the kernel. Update our structures. */ 30533bfb914e76943b35e96bbaead678c2c96f3380edflorian nsegments[segR].end -= delta; 30543bfb914e76943b35e96bbaead678c2c96f3380edflorian nsegments[segA].start -= delta; 30553bfb914e76943b35e96bbaead678c2c96f3380edflorian aspacem_assert(nsegments[segR].start <= nsegments[segR].end); 3056b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj } 3057b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj 305845f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 3059888b8159535580b30550f99cb7361f62edd83100florian return nsegments + segA; 306098abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge} 306198abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 306279048ce723a3463c70257ce647f04b111de71863sewardj 306345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* --- --- --- resizing/move a mapping --- --- --- */ 3064646c6aa268d4f1e524f2a9b721eef7a62d87046dthughes 3065f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#if HAVE_MREMAP 3066f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3067dd7318bea2a008f15085e12e026a78a6802e2e9cflorian/* This function grows a client mapping in place into an adjacent free segment. 3068dd7318bea2a008f15085e12e026a78a6802e2e9cflorian ADDR is the client mapping's start address and DELTA, which must be page 3069dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aligned, is the growth amount. The function returns a pointer to the 3070dd7318bea2a008f15085e12e026a78a6802e2e9cflorian resized segment. The function is used in support of mremap. */ 3071dd7318bea2a008f15085e12e026a78a6802e2e9cflorianconst NSegment *VG_(am_extend_map_client)( Addr addr, SizeT delta ) 307245f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 307345f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr xStart; 307445f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 30759aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes 307663a622f4da0254c435348f2c78b31aa66f4549c8sewardj if (0) 307763a622f4da0254c435348f2c78b31aa66f4549c8sewardj VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) BEFORE"); 307863a622f4da0254c435348f2c78b31aa66f4549c8sewardj 3079dd7318bea2a008f15085e12e026a78a6802e2e9cflorian /* Get the client segment */ 3080dd7318bea2a008f15085e12e026a78a6802e2e9cflorian Int ix = find_nsegment_idx(addr); 3081dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aspacem_assert(ix >= 0 && ix < nsegments_used); 30829aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes 3083dd7318bea2a008f15085e12e026a78a6802e2e9cflorian NSegment *seg = nsegments + ix; 3084dd7318bea2a008f15085e12e026a78a6802e2e9cflorian 30857a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian aspacem_assert(seg->kind == SkFileC || seg->kind == SkAnonC || 30867a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian seg->kind == SkShmC); 3087dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aspacem_assert(delta > 0 && VG_IS_PAGE_ALIGNED(delta)) ; 3088394790db0f8e9ce913e12df8555af7155b9aa0bdsewardj 308945f4e7c91119c7d01a59f5e827c67841632c9314sewardj xStart = seg->end+1; 3090dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aspacem_assert(xStart + delta >= delta); // no wrap-around 30919aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes 3092dd7318bea2a008f15085e12e026a78a6802e2e9cflorian /* The segment following the client segment must be a free segment and 3093dd7318bea2a008f15085e12e026a78a6802e2e9cflorian it must be large enough to cover the additional memory. */ 3094dd7318bea2a008f15085e12e026a78a6802e2e9cflorian NSegment *segf = seg + 1; 3095dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aspacem_assert(segf->kind == SkFree); 3096dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aspacem_assert(segf->start == xStart); 3097dd7318bea2a008f15085e12e026a78a6802e2e9cflorian aspacem_assert(xStart + delta - 1 <= segf->end); 3098dd7318bea2a008f15085e12e026a78a6802e2e9cflorian 3099dd7318bea2a008f15085e12e026a78a6802e2e9cflorian SizeT seg_old_len = seg->end + 1 - seg->start; 31009aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes 310145f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 3102297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj sres = ML_(am_do_extend_mapping_NO_NOTIFY)( seg->start, 3103297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj seg_old_len, 3104297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj seg_old_len + delta ); 3105cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 310645f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 3107dd7318bea2a008f15085e12e026a78a6802e2e9cflorian return NULL; 310863a622f4da0254c435348f2c78b31aa66f4549c8sewardj } else { 310963a622f4da0254c435348f2c78b31aa66f4549c8sewardj /* the area must not have moved */ 3110cda2f0fbda4c4b2644babc830244be8aed95de1dnjn aspacem_assert(sr_Res(sres) == seg->start); 31119aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes } 31129aaebc3476170f0776fe2e246bbc8baea6cc64fbthughes 3113dd7318bea2a008f15085e12e026a78a6802e2e9cflorian NSegment seg_copy = *seg; 311445f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg_copy.end += delta; 311545f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg_copy ); 3116548be6d64c58729588a559b1512ad7625bc1b86esewardj 311763a622f4da0254c435348f2c78b31aa66f4549c8sewardj if (0) 311863a622f4da0254c435348f2c78b31aa66f4549c8sewardj VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) AFTER"); 311963a622f4da0254c435348f2c78b31aa66f4549c8sewardj 312045f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 3121dd7318bea2a008f15085e12e026a78a6802e2e9cflorian return nsegments + find_nsegment_idx(addr); 3122548be6d64c58729588a559b1512ad7625bc1b86esewardj} 3123548be6d64c58729588a559b1512ad7625bc1b86esewardj 3124548be6d64c58729588a559b1512ad7625bc1b86esewardj 312545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Remap the old address range to the new address range. Fails if any 312645f4e7c91119c7d01a59f5e827c67841632c9314sewardj parameter is not page aligned, if the either size is zero, if any 312745f4e7c91119c7d01a59f5e827c67841632c9314sewardj wraparound is implied, if the old address range does not fall 312845f4e7c91119c7d01a59f5e827c67841632c9314sewardj entirely within a single segment, if the new address range overlaps 312945f4e7c91119c7d01a59f5e827c67841632c9314sewardj with the old one, or if the old address range is not a valid client 313045f4e7c91119c7d01a59f5e827c67841632c9314sewardj mapping. If *need_discard is True after a successful return, the 313145f4e7c91119c7d01a59f5e827c67841632c9314sewardj caller should immediately discard translations from both specified 313245f4e7c91119c7d01a59f5e827c67841632c9314sewardj address ranges. */ 3133b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj 313445f4e7c91119c7d01a59f5e827c67841632c9314sewardjBool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, 313545f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr old_addr, SizeT old_len, 313645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Addr new_addr, SizeT new_len ) 3137855d93d2e9940890b28874520fa4c1677bf825e2jsgf{ 313845f4e7c91119c7d01a59f5e827c67841632c9314sewardj Int iLo, iHi; 313945f4e7c91119c7d01a59f5e827c67841632c9314sewardj SysRes sres; 3140fcb3bc99945217eb66980488b933a6b65dc2f091tom NSegment seg; 3141855d93d2e9940890b28874520fa4c1677bf825e2jsgf 314245f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (old_len == 0 || new_len == 0) 314345f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 3144b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj 314545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (!VG_IS_PAGE_ALIGNED(old_addr) || !VG_IS_PAGE_ALIGNED(old_len) 314645f4e7c91119c7d01a59f5e827c67841632c9314sewardj || !VG_IS_PAGE_ALIGNED(new_addr) || !VG_IS_PAGE_ALIGNED(new_len)) 314745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 3148b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj 314945f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (old_addr + old_len < old_addr 315045f4e7c91119c7d01a59f5e827c67841632c9314sewardj || new_addr + new_len < new_addr) 315145f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 3152b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj 315345f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (old_addr + old_len - 1 < new_addr 315445f4e7c91119c7d01a59f5e827c67841632c9314sewardj || new_addr + new_len - 1 < old_addr) { 315545f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* no overlap */ 315645f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else 315745f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 3158855d93d2e9940890b28874520fa4c1677bf825e2jsgf 315945f4e7c91119c7d01a59f5e827c67841632c9314sewardj iLo = find_nsegment_idx( old_addr ); 316045f4e7c91119c7d01a59f5e827c67841632c9314sewardj iHi = find_nsegment_idx( old_addr + old_len - 1 ); 316145f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (iLo != iHi) 316245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 3163b5f6f51ebcac183818061bf53427a3e7808ef10dsewardj 31647a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian if (nsegments[iLo].kind != SkFileC && nsegments[iLo].kind != SkAnonC && 31657a5681fd96d9ccf3527daf6a32a0378fe2ca7faeflorian nsegments[iLo].kind != SkShmC) 316645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 316798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 3168297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj sres = ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY) 3169297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ( old_addr, old_len, new_addr, new_len ); 3170cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(sres)) { 317145f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 317245f4e7c91119c7d01a59f5e827c67841632c9314sewardj return False; 3173ee2de2c04815768bd994d3c341e736eca1e72175sewardj } else { 3174cda2f0fbda4c4b2644babc830244be8aed95de1dnjn aspacem_assert(sr_Res(sres) == new_addr); 317545f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 317686f12dca3206f958abe000ff8c7de58098e0897cnjn 317745f4e7c91119c7d01a59f5e827c67841632c9314sewardj *need_discard = any_Ts_in_range( old_addr, old_len ) 317845f4e7c91119c7d01a59f5e827c67841632c9314sewardj || any_Ts_in_range( new_addr, new_len ); 317986f12dca3206f958abe000ff8c7de58098e0897cnjn 3180fcb3bc99945217eb66980488b933a6b65dc2f091tom seg = nsegments[iLo]; 3181fcb3bc99945217eb66980488b933a6b65dc2f091tom 3182fcb3bc99945217eb66980488b933a6b65dc2f091tom /* Mark the new area based on the old seg. */ 3183fcb3bc99945217eb66980488b933a6b65dc2f091tom if (seg.kind == SkFileC) { 3184fcb3bc99945217eb66980488b933a6b65dc2f091tom seg.offset += ((ULong)old_addr) - ((ULong)seg.start); 3185fcb3bc99945217eb66980488b933a6b65dc2f091tom } 3186fcb3bc99945217eb66980488b933a6b65dc2f091tom seg.start = new_addr; 3187fcb3bc99945217eb66980488b933a6b65dc2f091tom seg.end = new_addr + new_len - 1; 3188fcb3bc99945217eb66980488b933a6b65dc2f091tom add_segment( &seg ); 318986f12dca3206f958abe000ff8c7de58098e0897cnjn 319045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Create a free hole in the old location. */ 319145f4e7c91119c7d01a59f5e827c67841632c9314sewardj init_nsegment( &seg ); 319245f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.start = old_addr; 319345f4e7c91119c7d01a59f5e827c67841632c9314sewardj seg.end = old_addr + old_len - 1; 3194613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj /* See comments in VG_(am_notify_munmap) about this SkResvn vs 3195613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj SkFree thing. */ 3196613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj if (old_addr > aspacem_maxAddr 3197613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj && /* check previous comparison is meaningful */ 3198613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj aspacem_maxAddr < Addr_MAX) 3199613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj seg.kind = SkResvn; 3200613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj else 3201613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj seg.kind = SkFree; 3202613a9f26e5b66b34c4031bdb9452c11c0a006d57sewardj 320345f4e7c91119c7d01a59f5e827c67841632c9314sewardj add_segment( &seg ); 320486f12dca3206f958abe000ff8c7de58098e0897cnjn 320545f4e7c91119c7d01a59f5e827c67841632c9314sewardj AM_SANITY_CHECK; 320645f4e7c91119c7d01a59f5e827c67841632c9314sewardj return True; 320798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge} 320898abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge 3209f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#endif // HAVE_MREMAP 3210f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3211f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3212c401ae7ea8e709040d70a2ea6e2e44979aa90ac0bart#if defined(VGO_linux) 3213c401ae7ea8e709040d70a2ea6e2e44979aa90ac0bart 321445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*-----------------------------------------------------------------*/ 321545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- ---*/ 3216cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- A simple parser for /proc/self/maps on Linux 2.4.X/2.6.X. ---*/ 3217cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- Almost completely independent of the stuff above. The ---*/ 3218cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- only function it 'exports' to the code above this comment ---*/ 3219cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- is parse_procselfmaps. ---*/ 3220cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*--- ---*/ 3221cb249ab3febb3757a0b0582be21952efacf415e5sewardj/*-----------------------------------------------------------------*/ 3222cb249ab3febb3757a0b0582be21952efacf415e5sewardj 322338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------BEGIN-procmaps-parser-for-Linux--------------------------*/ 322438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 3225cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Size of a smallish table used to read /proc/self/map entries. */ 3226cb249ab3febb3757a0b0582be21952efacf415e5sewardj#define M_PROCMAP_BUF 100000 3227cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3228cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* static ... to keep it out of the stack frame. */ 3229dbb3584f591710a15a437918c0fc27e300993566florianstatic HChar procmap_buf[M_PROCMAP_BUF]; 3230cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3231cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Records length of /proc/self/maps read into procmap_buf. */ 3232cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic Int buf_n_tot; 3233cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3234cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Helper fns. */ 3235cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3236dbb3584f591710a15a437918c0fc27e300993566florianstatic Int hexdigit ( HChar c ) 3237cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3238cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (c >= '0' && c <= '9') return (Int)(c - '0'); 3239cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (c >= 'a' && c <= 'f') return 10 + (Int)(c - 'a'); 3240cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (c >= 'A' && c <= 'F') return 10 + (Int)(c - 'A'); 3241cb249ab3febb3757a0b0582be21952efacf415e5sewardj return -1; 3242cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3243cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3244dbb3584f591710a15a437918c0fc27e300993566florianstatic Int decdigit ( HChar c ) 3245cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3246cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (c >= '0' && c <= '9') return (Int)(c - '0'); 3247cb249ab3febb3757a0b0582be21952efacf415e5sewardj return -1; 3248cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3249cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3250dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readchar ( const HChar* buf, HChar* ch ) 3251cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3252cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (*buf == 0) return 0; 3253cb249ab3febb3757a0b0582be21952efacf415e5sewardj *ch = *buf; 3254cb249ab3febb3757a0b0582be21952efacf415e5sewardj return 1; 3255cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3256cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3257dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readhex ( const HChar* buf, UWord* val ) 3258cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3259274461dcb67f680196c97e8afb7028a79b97dcb7sewardj /* Read a word-sized hex number. */ 3260274461dcb67f680196c97e8afb7028a79b97dcb7sewardj Int n = 0; 3261274461dcb67f680196c97e8afb7028a79b97dcb7sewardj *val = 0; 3262274461dcb67f680196c97e8afb7028a79b97dcb7sewardj while (hexdigit(*buf) >= 0) { 3263274461dcb67f680196c97e8afb7028a79b97dcb7sewardj *val = (*val << 4) + hexdigit(*buf); 3264274461dcb67f680196c97e8afb7028a79b97dcb7sewardj n++; buf++; 3265274461dcb67f680196c97e8afb7028a79b97dcb7sewardj } 3266274461dcb67f680196c97e8afb7028a79b97dcb7sewardj return n; 3267274461dcb67f680196c97e8afb7028a79b97dcb7sewardj} 3268274461dcb67f680196c97e8afb7028a79b97dcb7sewardj 3269dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readhex64 ( const HChar* buf, ULong* val ) 3270274461dcb67f680196c97e8afb7028a79b97dcb7sewardj{ 3271274461dcb67f680196c97e8afb7028a79b97dcb7sewardj /* Read a potentially 64-bit hex number. */ 3272cb249ab3febb3757a0b0582be21952efacf415e5sewardj Int n = 0; 3273cb249ab3febb3757a0b0582be21952efacf415e5sewardj *val = 0; 3274cb249ab3febb3757a0b0582be21952efacf415e5sewardj while (hexdigit(*buf) >= 0) { 3275cb249ab3febb3757a0b0582be21952efacf415e5sewardj *val = (*val << 4) + hexdigit(*buf); 3276cb249ab3febb3757a0b0582be21952efacf415e5sewardj n++; buf++; 3277cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3278cb249ab3febb3757a0b0582be21952efacf415e5sewardj return n; 3279cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3280cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3281dbb3584f591710a15a437918c0fc27e300993566florianstatic Int readdec64 ( const HChar* buf, ULong* val ) 3282cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3283cb249ab3febb3757a0b0582be21952efacf415e5sewardj Int n = 0; 3284cb249ab3febb3757a0b0582be21952efacf415e5sewardj *val = 0; 328554212b6475e26755d9ecf452b9cc44fbc5772b7eflorian while (decdigit(*buf) >= 0) { 3286cb249ab3febb3757a0b0582be21952efacf415e5sewardj *val = (*val * 10) + decdigit(*buf); 3287cb249ab3febb3757a0b0582be21952efacf415e5sewardj n++; buf++; 3288cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3289cb249ab3febb3757a0b0582be21952efacf415e5sewardj return n; 3290cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3291cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3292cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3293cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Get the contents of /proc/self/maps into a static buffer. If 3294cb249ab3febb3757a0b0582be21952efacf415e5sewardj there's a syntax error, it won't fit, or other failure, just 3295cb249ab3febb3757a0b0582be21952efacf415e5sewardj abort. */ 3296cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3297cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic void read_procselfmaps_into_buf ( void ) 3298cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3299cb249ab3febb3757a0b0582be21952efacf415e5sewardj Int n_chunk; 3300cb249ab3febb3757a0b0582be21952efacf415e5sewardj SysRes fd; 3301cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3302cb249ab3febb3757a0b0582be21952efacf415e5sewardj /* Read the initial memory mapping from the /proc filesystem. */ 3303297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj fd = ML_(am_open)( "/proc/self/maps", VKI_O_RDONLY, 0 ); 3304cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(fd)) 3305297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ML_(am_barf)("can't open /proc/self/maps"); 3306cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3307cb249ab3febb3757a0b0582be21952efacf415e5sewardj buf_n_tot = 0; 3308cb249ab3febb3757a0b0582be21952efacf415e5sewardj do { 3309cda2f0fbda4c4b2644babc830244be8aed95de1dnjn n_chunk = ML_(am_read)( sr_Res(fd), &procmap_buf[buf_n_tot], 3310cb249ab3febb3757a0b0582be21952efacf415e5sewardj M_PROCMAP_BUF - buf_n_tot ); 3311297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj if (n_chunk >= 0) 3312297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj buf_n_tot += n_chunk; 3313cb249ab3febb3757a0b0582be21952efacf415e5sewardj } while ( n_chunk > 0 && buf_n_tot < M_PROCMAP_BUF ); 3314cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3315cda2f0fbda4c4b2644babc830244be8aed95de1dnjn ML_(am_close)(sr_Res(fd)); 3316cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3317cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (buf_n_tot >= M_PROCMAP_BUF-5) 3318297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ML_(am_barf_toolow)("M_PROCMAP_BUF"); 3319cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (buf_n_tot == 0) 3320297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ML_(am_barf)("I/O error on /proc/self/maps"); 3321cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3322cb249ab3febb3757a0b0582be21952efacf415e5sewardj procmap_buf[buf_n_tot] = 0; 3323cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3324cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3325cb249ab3febb3757a0b0582be21952efacf415e5sewardj/* Parse /proc/self/maps. For each map entry, call 3326cb249ab3febb3757a0b0582be21952efacf415e5sewardj record_mapping, passing it, in this order: 3327cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3328cb249ab3febb3757a0b0582be21952efacf415e5sewardj start address in memory 3329cb249ab3febb3757a0b0582be21952efacf415e5sewardj length 3330cb249ab3febb3757a0b0582be21952efacf415e5sewardj page protections (using the VKI_PROT_* flags) 3331cb249ab3febb3757a0b0582be21952efacf415e5sewardj mapped file device and inode 3332cb249ab3febb3757a0b0582be21952efacf415e5sewardj offset in file, or zero if no file 3333cb249ab3febb3757a0b0582be21952efacf415e5sewardj filename, zero terminated, or NULL if no file 3334cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3335cb249ab3febb3757a0b0582be21952efacf415e5sewardj So the sig of the called fn might be 3336cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3337cb249ab3febb3757a0b0582be21952efacf415e5sewardj void (*record_mapping)( Addr start, SizeT size, UInt prot, 3338cb249ab3febb3757a0b0582be21952efacf415e5sewardj UInt dev, UInt info, 3339cb249ab3febb3757a0b0582be21952efacf415e5sewardj ULong foffset, UChar* filename ) 3340cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3341cb249ab3febb3757a0b0582be21952efacf415e5sewardj Note that the supplied filename is transiently stored; record_mapping 3342cb249ab3febb3757a0b0582be21952efacf415e5sewardj should make a copy if it wants to keep it. 3343cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3344cb249ab3febb3757a0b0582be21952efacf415e5sewardj Nb: it is important that this function does not alter the contents of 3345cb249ab3febb3757a0b0582be21952efacf415e5sewardj procmap_buf! 3346cb249ab3febb3757a0b0582be21952efacf415e5sewardj*/ 3347cb249ab3febb3757a0b0582be21952efacf415e5sewardjstatic void parse_procselfmaps ( 3348cb249ab3febb3757a0b0582be21952efacf415e5sewardj void (*record_mapping)( Addr addr, SizeT len, UInt prot, 3349c4431bfe04c7490ea2d74939d222d87f13f30960njn ULong dev, ULong ino, Off64T offset, 3350dbb3584f591710a15a437918c0fc27e300993566florian const HChar* filename ), 3351cb249ab3febb3757a0b0582be21952efacf415e5sewardj void (*record_gap)( Addr addr, SizeT len ) 3352cb249ab3febb3757a0b0582be21952efacf415e5sewardj ) 3353cb249ab3febb3757a0b0582be21952efacf415e5sewardj{ 3354cb249ab3febb3757a0b0582be21952efacf415e5sewardj Int i, j, i_eol; 3355cb249ab3febb3757a0b0582be21952efacf415e5sewardj Addr start, endPlusOne, gapStart; 3356dbb3584f591710a15a437918c0fc27e300993566florian HChar* filename; 3357dbb3584f591710a15a437918c0fc27e300993566florian HChar rr, ww, xx, pp, ch, tmp; 3358419060073e7943846cc9e0bcdcb25258d90da2dcsewardj UInt prot; 3359419060073e7943846cc9e0bcdcb25258d90da2dcsewardj UWord maj, min; 3360419060073e7943846cc9e0bcdcb25258d90da2dcsewardj ULong foffset, dev, ino; 3361cb249ab3febb3757a0b0582be21952efacf415e5sewardj 33624c3faae4aa73a0693c66a24daccf8bc0a0e421f7sewardj foffset = ino = 0; /* keep gcc-4.1.0 happy */ 33634c3faae4aa73a0693c66a24daccf8bc0a0e421f7sewardj 3364cb249ab3febb3757a0b0582be21952efacf415e5sewardj read_procselfmaps_into_buf(); 3365cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3366cb249ab3febb3757a0b0582be21952efacf415e5sewardj aspacem_assert('\0' != procmap_buf[0] && 0 != buf_n_tot); 3367cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3368cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (0) 3369cb249ab3febb3757a0b0582be21952efacf415e5sewardj VG_(debugLog)(0, "procselfmaps", "raw:\n%s\n", procmap_buf); 3370cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3371cb249ab3febb3757a0b0582be21952efacf415e5sewardj /* Ok, it's safely aboard. Parse the entries. */ 3372cb249ab3febb3757a0b0582be21952efacf415e5sewardj i = 0; 3373cb249ab3febb3757a0b0582be21952efacf415e5sewardj gapStart = Addr_MIN; 3374cb249ab3febb3757a0b0582be21952efacf415e5sewardj while (True) { 3375cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (i >= buf_n_tot) break; 3376cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3377cb249ab3febb3757a0b0582be21952efacf415e5sewardj /* Read (without fscanf :) the pattern %16x-%16x %c%c%c%c %16x %2x:%2x %d */ 3378cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readhex(&procmap_buf[i], &start); 3379cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j > 0) i += j; else goto syntaxerror; 3380cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ch); 3381cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && ch == '-') i += j; else goto syntaxerror; 3382cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readhex(&procmap_buf[i], &endPlusOne); 3383cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j > 0) i += j; else goto syntaxerror; 3384cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3385cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ch); 3386cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3387cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3388cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &rr); 3389cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && (rr == 'r' || rr == '-')) i += j; else goto syntaxerror; 3390cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ww); 3391cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && (ww == 'w' || ww == '-')) i += j; else goto syntaxerror; 3392cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &xx); 3393cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && (xx == 'x' || xx == '-')) i += j; else goto syntaxerror; 3394cb249ab3febb3757a0b0582be21952efacf415e5sewardj /* This field is the shared/private flag */ 3395cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &pp); 3396cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && (pp == 'p' || pp == '-' || pp == 's')) 3397cb249ab3febb3757a0b0582be21952efacf415e5sewardj i += j; else goto syntaxerror; 3398cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3399cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ch); 3400cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3401cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3402274461dcb67f680196c97e8afb7028a79b97dcb7sewardj j = readhex64(&procmap_buf[i], &foffset); 3403cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j > 0) i += j; else goto syntaxerror; 3404cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3405cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ch); 3406cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3407cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3408cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readhex(&procmap_buf[i], &maj); 3409cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j > 0) i += j; else goto syntaxerror; 3410cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ch); 3411cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && ch == ':') i += j; else goto syntaxerror; 3412cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readhex(&procmap_buf[i], &min); 3413cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j > 0) i += j; else goto syntaxerror; 3414cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3415cb249ab3febb3757a0b0582be21952efacf415e5sewardj j = readchar(&procmap_buf[i], &ch); 3416cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3417cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3418419060073e7943846cc9e0bcdcb25258d90da2dcsewardj j = readdec64(&procmap_buf[i], &ino); 3419cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (j > 0) i += j; else goto syntaxerror; 3420cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3421cb249ab3febb3757a0b0582be21952efacf415e5sewardj goto read_line_ok; 3422cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3423cb249ab3febb3757a0b0582be21952efacf415e5sewardj syntaxerror: 3424cb249ab3febb3757a0b0582be21952efacf415e5sewardj VG_(debugLog)(0, "Valgrind:", 3425cb249ab3febb3757a0b0582be21952efacf415e5sewardj "FATAL: syntax error reading /proc/self/maps\n"); 3426cb249ab3febb3757a0b0582be21952efacf415e5sewardj { Int k, m; 3427cb249ab3febb3757a0b0582be21952efacf415e5sewardj HChar buf50[51]; 3428cb249ab3febb3757a0b0582be21952efacf415e5sewardj m = 0; 3429cb249ab3febb3757a0b0582be21952efacf415e5sewardj buf50[m] = 0; 3430cb249ab3febb3757a0b0582be21952efacf415e5sewardj k = i - 50; 3431cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (k < 0) k = 0; 3432cb249ab3febb3757a0b0582be21952efacf415e5sewardj for (; k <= i; k++) { 3433cb249ab3febb3757a0b0582be21952efacf415e5sewardj buf50[m] = procmap_buf[k]; 3434cb249ab3febb3757a0b0582be21952efacf415e5sewardj buf50[m+1] = 0; 3435cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (m < 50-1) m++; 3436cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3437cb249ab3febb3757a0b0582be21952efacf415e5sewardj VG_(debugLog)(0, "procselfmaps", "Last 50 chars: '%s'\n", buf50); 3438cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3439297f6b0565fd0bb08fd3ddc1f2377ee6b3306b82sewardj ML_(am_exit)(1); 3440cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3441cb249ab3febb3757a0b0582be21952efacf415e5sewardj read_line_ok: 3442cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3443bd28c5e5dbdf69de901c025f67d4c1af24175492florian aspacem_assert(i < buf_n_tot); 3444bd28c5e5dbdf69de901c025f67d4c1af24175492florian 3445cb249ab3febb3757a0b0582be21952efacf415e5sewardj /* Try and find the name of the file mapped to this segment, if 3446bd28c5e5dbdf69de901c025f67d4c1af24175492florian it exists. Note that file names can contain spaces. */ 3447cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3448bd28c5e5dbdf69de901c025f67d4c1af24175492florian // Move i to the next non-space char, which should be either a '/', 3449bd28c5e5dbdf69de901c025f67d4c1af24175492florian // a '[', or a newline. 3450bd28c5e5dbdf69de901c025f67d4c1af24175492florian while (procmap_buf[i] == ' ') i++; 3451cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3452cb249ab3febb3757a0b0582be21952efacf415e5sewardj // Move i_eol to the end of the line. 3453cb249ab3febb3757a0b0582be21952efacf415e5sewardj i_eol = i; 3454bd28c5e5dbdf69de901c025f67d4c1af24175492florian while (procmap_buf[i_eol] != '\n') i_eol++; 3455cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3456cb249ab3febb3757a0b0582be21952efacf415e5sewardj // If there's a filename... 3457bd28c5e5dbdf69de901c025f67d4c1af24175492florian if (procmap_buf[i] == '/') { 3458cb249ab3febb3757a0b0582be21952efacf415e5sewardj /* Minor hack: put a '\0' at the filename end for the call to 3459cb249ab3febb3757a0b0582be21952efacf415e5sewardj 'record_mapping', then restore the old char with 'tmp'. */ 3460cb249ab3febb3757a0b0582be21952efacf415e5sewardj filename = &procmap_buf[i]; 3461cb249ab3febb3757a0b0582be21952efacf415e5sewardj tmp = filename[i_eol - i]; 3462cb249ab3febb3757a0b0582be21952efacf415e5sewardj filename[i_eol - i] = '\0'; 3463cb249ab3febb3757a0b0582be21952efacf415e5sewardj } else { 3464cb249ab3febb3757a0b0582be21952efacf415e5sewardj tmp = 0; 3465cb249ab3febb3757a0b0582be21952efacf415e5sewardj filename = NULL; 3466cb249ab3febb3757a0b0582be21952efacf415e5sewardj foffset = 0; 3467cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3468cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3469cb249ab3febb3757a0b0582be21952efacf415e5sewardj prot = 0; 3470cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (rr == 'r') prot |= VKI_PROT_READ; 3471cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (ww == 'w') prot |= VKI_PROT_WRITE; 3472cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (xx == 'x') prot |= VKI_PROT_EXEC; 3473cb249ab3febb3757a0b0582be21952efacf415e5sewardj 347499ffec4b2a139513c77a420a459d5ea9beaadb98tom /* Linux has two ways to encode a device number when it 347599ffec4b2a139513c77a420a459d5ea9beaadb98tom is exposed to user space (via fstat etc). The old way 347699ffec4b2a139513c77a420a459d5ea9beaadb98tom is the traditional unix scheme that produces a 16 bit 347799ffec4b2a139513c77a420a459d5ea9beaadb98tom device number with the top 8 being the major number and 347899ffec4b2a139513c77a420a459d5ea9beaadb98tom the bottom 8 the minor number. 347999ffec4b2a139513c77a420a459d5ea9beaadb98tom 348099ffec4b2a139513c77a420a459d5ea9beaadb98tom The new scheme allows for a 12 bit major number and 348199ffec4b2a139513c77a420a459d5ea9beaadb98tom a 20 bit minor number by using a 32 bit device number 348299ffec4b2a139513c77a420a459d5ea9beaadb98tom and putting the top 12 bits of the minor number into 348399ffec4b2a139513c77a420a459d5ea9beaadb98tom the top 12 bits of the device number thus leaving an 348499ffec4b2a139513c77a420a459d5ea9beaadb98tom extra 4 bits for the major number. 348599ffec4b2a139513c77a420a459d5ea9beaadb98tom 348699ffec4b2a139513c77a420a459d5ea9beaadb98tom If the minor and major number are both single byte 348799ffec4b2a139513c77a420a459d5ea9beaadb98tom values then both schemes give the same result so we 348899ffec4b2a139513c77a420a459d5ea9beaadb98tom use the new scheme here in case either number is 348999ffec4b2a139513c77a420a459d5ea9beaadb98tom outside the 0-255 range and then use fstat64 when 349099ffec4b2a139513c77a420a459d5ea9beaadb98tom available (or fstat on 64 bit systems) so that we 349199ffec4b2a139513c77a420a459d5ea9beaadb98tom should always have a new style device number and 349299ffec4b2a139513c77a420a459d5ea9beaadb98tom everything should match. */ 349399ffec4b2a139513c77a420a459d5ea9beaadb98tom dev = (min & 0xff) | (maj << 8) | ((min & ~0xff) << 12); 349499ffec4b2a139513c77a420a459d5ea9beaadb98tom 3495cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (record_gap && gapStart < start) 3496cb249ab3febb3757a0b0582be21952efacf415e5sewardj (*record_gap) ( gapStart, start-gapStart ); 3497cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3498e6bbc36e0095970ded2564c1763026c79ccadbdesewardj if (record_mapping && start < endPlusOne) 3499e6bbc36e0095970ded2564c1763026c79ccadbdesewardj (*record_mapping) ( start, endPlusOne-start, 3500e6bbc36e0095970ded2564c1763026c79ccadbdesewardj prot, dev, ino, 3501e6bbc36e0095970ded2564c1763026c79ccadbdesewardj foffset, filename ); 3502cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3503cb249ab3febb3757a0b0582be21952efacf415e5sewardj if ('\0' != tmp) { 3504cb249ab3febb3757a0b0582be21952efacf415e5sewardj filename[i_eol - i] = tmp; 3505cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3506cb249ab3febb3757a0b0582be21952efacf415e5sewardj 3507cb249ab3febb3757a0b0582be21952efacf415e5sewardj i = i_eol + 1; 3508cb249ab3febb3757a0b0582be21952efacf415e5sewardj gapStart = endPlusOne; 3509cb249ab3febb3757a0b0582be21952efacf415e5sewardj } 3510cb249ab3febb3757a0b0582be21952efacf415e5sewardj 351138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj# if defined(VGP_arm_linux) 351238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj /* ARM puts code at the end of memory that contains processor 351338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj specific stuff (cmpxchg, getting the thread local storage, etc.) 351438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj This isn't specified in /proc/self/maps, so do it here. This 351538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj kludgery causes the view of memory, as presented to 351638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj record_gap/record_mapping, to actually reflect reality. IMO 351738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj (JRS, 2010-Jan-03) the fact that /proc/.../maps does not list 351838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj the commpage should be regarded as a bug in the kernel. */ 351938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj { const Addr commpage_start = ARM_LINUX_FAKE_COMMPAGE_START; 352038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj const Addr commpage_end1 = ARM_LINUX_FAKE_COMMPAGE_END1; 352138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj if (gapStart < commpage_start) { 352238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj if (record_gap) 352338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj (*record_gap)( gapStart, commpage_start - gapStart ); 352438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj if (record_mapping) 352538a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj (*record_mapping)( commpage_start, commpage_end1 - commpage_start, 352638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj VKI_PROT_READ|VKI_PROT_EXEC, 352738a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 0/*dev*/, 0/*ino*/, 0/*foffset*/, 352838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj NULL); 352938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj gapStart = commpage_end1; 353038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj } 353138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj } 353238a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj# endif 353338a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 3534cb249ab3febb3757a0b0582be21952efacf415e5sewardj if (record_gap && gapStart < Addr_MAX) 3535cb249ab3febb3757a0b0582be21952efacf415e5sewardj (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 ); 3536cb249ab3febb3757a0b0582be21952efacf415e5sewardj} 3537cb249ab3febb3757a0b0582be21952efacf415e5sewardj 353838a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------END-procmaps-parser-for-Linux----------------------------*/ 353938a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 354038a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------BEGIN-procmaps-parser-for-Darwin-------------------------*/ 354138a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj 3542f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#elif defined(VGO_darwin) 3543f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach/mach.h> 3544f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach/mach_vm.h> 3545f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3546f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic unsigned int mach2vki(unsigned int vm_prot) 3547f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 3548f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 3549f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ((vm_prot & VM_PROT_READ) ? VKI_PROT_READ : 0) | 3550f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ((vm_prot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) | 3551f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ((vm_prot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0) ; 3552f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 3553f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3554f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic UInt stats_machcalls = 0; 3555f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3556f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void parse_procselfmaps ( 3557f76d27a697a7b0bf3b84490baf60623fc96a23afnjn void (*record_mapping)( Addr addr, SizeT len, UInt prot, 3558f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ULong dev, ULong ino, Off64T offset, 3559dbb3584f591710a15a437918c0fc27e300993566florian const HChar* filename ), 3560f76d27a697a7b0bf3b84490baf60623fc96a23afnjn void (*record_gap)( Addr addr, SizeT len ) 3561f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ) 3562f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 3563f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vm_address_t iter; 3564f76d27a697a7b0bf3b84490baf60623fc96a23afnjn unsigned int depth; 3565f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vm_address_t last; 3566f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3567f76d27a697a7b0bf3b84490baf60623fc96a23afnjn iter = 0; 3568f76d27a697a7b0bf3b84490baf60623fc96a23afnjn depth = 0; 3569f76d27a697a7b0bf3b84490baf60623fc96a23afnjn last = 0; 3570f76d27a697a7b0bf3b84490baf60623fc96a23afnjn while (1) { 3571f76d27a697a7b0bf3b84490baf60623fc96a23afnjn mach_vm_address_t addr = iter; 3572f76d27a697a7b0bf3b84490baf60623fc96a23afnjn mach_vm_size_t size; 3573f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vm_region_submap_short_info_data_64_t info; 3574f76d27a697a7b0bf3b84490baf60623fc96a23afnjn kern_return_t kr; 3575f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3576f76d27a697a7b0bf3b84490baf60623fc96a23afnjn while (1) { 3577f76d27a697a7b0bf3b84490baf60623fc96a23afnjn mach_msg_type_number_t info_count 3578f76d27a697a7b0bf3b84490baf60623fc96a23afnjn = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 3579f76d27a697a7b0bf3b84490baf60623fc96a23afnjn stats_machcalls++; 3580f76d27a697a7b0bf3b84490baf60623fc96a23afnjn kr = mach_vm_region_recurse(mach_task_self(), &addr, &size, &depth, 3581f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (vm_region_info_t)&info, &info_count); 3582f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (kr) 3583f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return; 3584f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (info.is_submap) { 3585f76d27a697a7b0bf3b84490baf60623fc96a23afnjn depth++; 3586f76d27a697a7b0bf3b84490baf60623fc96a23afnjn continue; 3587f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3588f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 3589f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3590f76d27a697a7b0bf3b84490baf60623fc96a23afnjn iter = addr + size; 3591f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3592f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (addr > last && record_gap) { 3593f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (*record_gap)(last, addr - last); 3594f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3595f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (record_mapping) { 3596f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (*record_mapping)(addr, size, mach2vki(info.protection), 3597f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 0, 0, info.offset, NULL); 3598f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3599f76d27a697a7b0bf3b84490baf60623fc96a23afnjn last = addr + size; 3600f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3601f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3602f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if ((Addr)-1 > last && record_gap) 3603f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (*record_gap)(last, (Addr)-1 - last); 3604f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 3605f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 36069edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardj// Urr. So much for thread safety. 36079edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic Bool css_overflowed; 36089edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic ChangedSeg* css_local; 36099edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic Int css_size_local; 36109edd09f2aa4555db69fde8c78dedc8f8fb30e46bsewardjstatic Int css_used_local; 3611f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3612e139a46c2961c48392005fb367ef6380ea57df4bsewardjstatic Addr Addr__max ( Addr a, Addr b ) { return a > b ? a : b; } 3613e139a46c2961c48392005fb367ef6380ea57df4bsewardjstatic Addr Addr__min ( Addr a, Addr b ) { return a < b ? a : b; } 3614e139a46c2961c48392005fb367ef6380ea57df4bsewardj 3615f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void add_mapping_callback(Addr addr, SizeT len, UInt prot, 3616f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ULong dev, ULong ino, Off64T offset, 3617dbb3584f591710a15a437918c0fc27e300993566florian const HChar *filename) 3618f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 3619f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // derived from sync_check_mapping_callback() 3620f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3621e139a46c2961c48392005fb367ef6380ea57df4bsewardj /* JRS 2012-Mar-07: this all seems very dubious to me. It would be 3622e139a46c2961c48392005fb367ef6380ea57df4bsewardj safer to see if we can find, in V's segment collection, one 3623e139a46c2961c48392005fb367ef6380ea57df4bsewardj single segment that completely covers the range [addr, +len) 3624e139a46c2961c48392005fb367ef6380ea57df4bsewardj (and possibly more), and that has the exact same other 3625e139a46c2961c48392005fb367ef6380ea57df4bsewardj properties (prot, dev, ino, offset, etc) as the data presented 3626e139a46c2961c48392005fb367ef6380ea57df4bsewardj here. If found, we just skip. Otherwise add the data presented 3627e139a46c2961c48392005fb367ef6380ea57df4bsewardj here into css_local[]. */ 3628e139a46c2961c48392005fb367ef6380ea57df4bsewardj 3629f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Int iLo, iHi, i; 3630f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3631f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (len == 0) return; 3632f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3633f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* The kernel should not give us wraparounds. */ 3634f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_assert(addr <= addr + len - 1); 3635f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3636f76d27a697a7b0bf3b84490baf60623fc96a23afnjn iLo = find_nsegment_idx( addr ); 3637f76d27a697a7b0bf3b84490baf60623fc96a23afnjn iHi = find_nsegment_idx( addr + len - 1 ); 3638f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3639f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* NSegments iLo .. iHi inclusive should agree with the presented 3640f76d27a697a7b0bf3b84490baf60623fc96a23afnjn data. */ 3641f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = iLo; i <= iHi; i++) { 3642f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3643f76d27a697a7b0bf3b84490baf60623fc96a23afnjn UInt seg_prot; 3644f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3645f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (nsegments[i].kind == SkAnonV || nsegments[i].kind == SkFileV) { 3646f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Ignore V regions */ 3647f76d27a697a7b0bf3b84490baf60623fc96a23afnjn continue; 3648f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3649f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn) { 3650e139a46c2961c48392005fb367ef6380ea57df4bsewardj /* Add mapping for SkResvn regions */ 3651f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ChangedSeg* cs = &css_local[css_used_local]; 3652fd1b461d19d0fd0484682a51138308413a3eab0cnjn if (css_used_local < css_size_local) { 3653fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->is_added = True; 3654fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->start = addr; 3655fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->end = addr + len - 1; 3656fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->prot = prot; 3657fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->offset = offset; 3658fd1b461d19d0fd0484682a51138308413a3eab0cnjn css_used_local++; 3659fd1b461d19d0fd0484682a51138308413a3eab0cnjn } else { 3660fd1b461d19d0fd0484682a51138308413a3eab0cnjn css_overflowed = True; 3661fd1b461d19d0fd0484682a51138308413a3eab0cnjn } 3662f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return; 3663f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3664f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj } 3665f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj else if (nsegments[i].kind == SkAnonC || 3666f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj nsegments[i].kind == SkFileC || 3667f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj nsegments[i].kind == SkShmC) 3668f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 3669f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Check permissions on client regions */ 3670f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme 3671f76d27a697a7b0bf3b84490baf60623fc96a23afnjn seg_prot = 0; 3672f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ; 3673f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (nsegments[i].hasW) seg_prot |= VKI_PROT_WRITE; 3674f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# if defined(VGA_x86) 3675f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // GrP fixme sloppyXcheck 3676f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // darwin: kernel X ignored and spuriously changes? (vm_copy) 3677f76d27a697a7b0bf3b84490baf60623fc96a23afnjn seg_prot |= (prot & VKI_PROT_EXEC); 3678f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# else 3679f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (nsegments[i].hasX) seg_prot |= VKI_PROT_EXEC; 3680f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# endif 3681f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (seg_prot != prot) { 3682f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (VG_(clo_trace_syscalls)) 368308a631925b44574c66af84dc7ffd9f50976a5fdfsewardj VG_(debugLog)(0,"aspacem","region %p..%p permission " 368408a631925b44574c66af84dc7ffd9f50976a5fdfsewardj "mismatch (kernel %x, V %x)\n", 3685f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (void*)nsegments[i].start, 3686f76d27a697a7b0bf3b84490baf60623fc96a23afnjn (void*)(nsegments[i].end+1), prot, seg_prot); 3687f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj /* Add mapping for regions with protection changes */ 3688f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj ChangedSeg* cs = &css_local[css_used_local]; 3689f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj if (css_used_local < css_size_local) { 3690f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj cs->is_added = True; 3691f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj cs->start = addr; 3692f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj cs->end = addr + len - 1; 3693f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj cs->prot = prot; 3694f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj cs->offset = offset; 3695f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj css_used_local++; 3696f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj } else { 3697f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj css_overflowed = True; 3698f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj } 3699f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj return; 3700f1a9bd244c900db7478b68f6fc0ca7aebd4fead7sewardj 3701f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3702f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3703f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else { 3704f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_assert(0); 3705f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3706f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3707f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 3708f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3709f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void remove_mapping_callback(Addr addr, SizeT len) 3710f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 3711f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // derived from sync_check_gap_callback() 3712f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3713f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Int iLo, iHi, i; 3714f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3715f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (len == 0) 3716f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return; 3717f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3718f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* The kernel should not give us wraparounds. */ 3719f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_assert(addr <= addr + len - 1); 3720f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3721f76d27a697a7b0bf3b84490baf60623fc96a23afnjn iLo = find_nsegment_idx( addr ); 3722f76d27a697a7b0bf3b84490baf60623fc96a23afnjn iHi = find_nsegment_idx( addr + len - 1 ); 3723f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3724f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* NSegments iLo .. iHi inclusive should agree with the presented data. */ 3725f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = iLo; i <= iHi; i++) { 3726e139a46c2961c48392005fb367ef6380ea57df4bsewardj if (nsegments[i].kind != SkFree && nsegments[i].kind != SkResvn) { 3727e139a46c2961c48392005fb367ef6380ea57df4bsewardj /* V has a mapping, kernel doesn't. Add to css_local[], 3728e139a46c2961c48392005fb367ef6380ea57df4bsewardj directives to chop off the part of the V mapping that 3729e139a46c2961c48392005fb367ef6380ea57df4bsewardj falls within the gap that the kernel tells us is 3730e139a46c2961c48392005fb367ef6380ea57df4bsewardj present. */ 3731f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ChangedSeg* cs = &css_local[css_used_local]; 3732fd1b461d19d0fd0484682a51138308413a3eab0cnjn if (css_used_local < css_size_local) { 3733fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->is_added = False; 3734e139a46c2961c48392005fb367ef6380ea57df4bsewardj cs->start = Addr__max(nsegments[i].start, addr); 3735e139a46c2961c48392005fb367ef6380ea57df4bsewardj cs->end = Addr__min(nsegments[i].end, addr + len - 1); 3736e139a46c2961c48392005fb367ef6380ea57df4bsewardj aspacem_assert(VG_IS_PAGE_ALIGNED(cs->start)); 3737e139a46c2961c48392005fb367ef6380ea57df4bsewardj aspacem_assert(VG_IS_PAGE_ALIGNED(cs->end+1)); 3738e139a46c2961c48392005fb367ef6380ea57df4bsewardj /* I don't think the following should fail. But if it 3739e139a46c2961c48392005fb367ef6380ea57df4bsewardj does, just omit the css_used_local++ in the cases where 3740e139a46c2961c48392005fb367ef6380ea57df4bsewardj it doesn't hold. */ 3741e139a46c2961c48392005fb367ef6380ea57df4bsewardj aspacem_assert(cs->start < cs->end); 3742fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->prot = 0; 3743fd1b461d19d0fd0484682a51138308413a3eab0cnjn cs->offset = 0; 3744fd1b461d19d0fd0484682a51138308413a3eab0cnjn css_used_local++; 3745fd1b461d19d0fd0484682a51138308413a3eab0cnjn } else { 3746fd1b461d19d0fd0484682a51138308413a3eab0cnjn css_overflowed = True; 3747fd1b461d19d0fd0484682a51138308413a3eab0cnjn } 3748f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3749f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 3750f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 3751f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3752f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3753fd1b461d19d0fd0484682a51138308413a3eab0cnjn// Returns False if 'css' wasn't big enough. 3754fd1b461d19d0fd0484682a51138308413a3eab0cnjnBool VG_(get_changed_segments)( 3755f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css, 3756f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Int css_size, /*OUT*/Int* css_used) 3757f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 3758f76d27a697a7b0bf3b84490baf60623fc96a23afnjn static UInt stats_synccalls = 1; 3759f76d27a697a7b0bf3b84490baf60623fc96a23afnjn aspacem_assert(when && where); 3760f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3761f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0) 3762f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(0,"aspacem", 3763f76d27a697a7b0bf3b84490baf60623fc96a23afnjn "[%u,%u] VG_(get_changed_segments)(%s, %s)\n", 3764f76d27a697a7b0bf3b84490baf60623fc96a23afnjn stats_synccalls++, stats_machcalls, when, where 3765f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ); 3766f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3767fd1b461d19d0fd0484682a51138308413a3eab0cnjn css_overflowed = False; 3768f76d27a697a7b0bf3b84490baf60623fc96a23afnjn css_local = css; 3769f76d27a697a7b0bf3b84490baf60623fc96a23afnjn css_size_local = css_size; 3770f76d27a697a7b0bf3b84490baf60623fc96a23afnjn css_used_local = 0; 3771f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3772f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Get the list of segs that need to be added/removed. 3773f76d27a697a7b0bf3b84490baf60623fc96a23afnjn parse_procselfmaps(&add_mapping_callback, &remove_mapping_callback); 3774f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 3775f76d27a697a7b0bf3b84490baf60623fc96a23afnjn *css_used = css_used_local; 3776fd1b461d19d0fd0484682a51138308413a3eab0cnjn 3777fd1b461d19d0fd0484682a51138308413a3eab0cnjn if (css_overflowed) { 3778fd1b461d19d0fd0484682a51138308413a3eab0cnjn aspacem_assert(css_used_local == css_size_local); 3779fd1b461d19d0fd0484682a51138308413a3eab0cnjn } 3780fd1b461d19d0fd0484682a51138308413a3eab0cnjn 3781fd1b461d19d0fd0484682a51138308413a3eab0cnjn return !css_overflowed; 3782f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 3783f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 378438a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj#endif // defined(VGO_darwin) 3785c401ae7ea8e709040d70a2ea6e2e44979aa90ac0bart 378638a21ac27cec0d1631ad91f8aa3eecd95fa5663bsewardj/*------END-procmaps-parser-for-Darwin---------------------------*/ 37878b68b64759254d514d98328c496cbd88cde4c9a5njn 37888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*------BEGIN-procmaps-parser-for-Solaris------------------------*/ 37898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 37908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#if defined(VGO_solaris) 37918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 37928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Note: /proc/self/xmap contains extended information about already 37938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj materialized mappings whereas /proc/self/rmap contains information about 37948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj all mappings including reserved but yet-to-materialize mappings (mmap'ed 37958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj with MAP_NORESERVE flag, such as thread stacks). But /proc/self/rmap does 37968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj not contain extended information found in /proc/self/xmap. Therefore 37978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj information from both sources need to be combined. 37988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */ 37998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38008eb8bab992e3998c33770b0cdb16059a8b918a06sewardjtypedef struct 38018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 38028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Addr addr; 38038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT size; 38048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj UInt prot; 38058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ULong dev; 38068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ULong ino; 38078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Off64T foffset; 38088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj HChar filename[VKI_PATH_MAX]; 38098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} Mapping; 38108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38118eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic SizeT read_proc_file(const HChar *filename, HChar *buf, 38128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT buf_size, const HChar *buf_size_name, 38138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT entry_size) 38148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 38158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SysRes res = ML_(am_open)(filename, VKI_O_RDONLY, 0); 38168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (sr_isError(res)) { 38178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj HChar message[100]; 38188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_sprintf)(message, "Cannot open %s.", filename); 38198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_barf)(message); 38208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 38218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Int fd = sr_Res(res); 38228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Int r = ML_(am_read)(fd, buf, buf_size); 38248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_close)(fd); 38258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (r < 0) { 38268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj HChar message[100]; 38278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_sprintf)(message, "I/O error on %s.", filename); 38288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_barf)(message); 38298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 38308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (r >= buf_size) 38328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_barf_toolow)(buf_size_name); 38338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (r % entry_size != 0) { 38358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj HChar message[100]; 38368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_sprintf)(message, "Bogus values read from %s.", filename); 38378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_barf)(message); 38388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 38398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return r / entry_size; 38418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 38428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38438eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic Mapping *next_xmap(const HChar *buffer, SizeT entries, SizeT *idx, 38448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Mapping *mapping) 38458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 38468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(idx); 38478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(mapping); 38488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (*idx >= entries) 38508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return NULL; /* No more entries */ 38518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj const vki_prxmap_t *map = (const vki_prxmap_t *)buffer + *idx; 38538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->addr = map->pr_vaddr; 38558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->size = map->pr_size; 38568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot = 0; 38588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mflags & VKI_MA_READ) 38598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot |= VKI_PROT_READ; 38608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mflags & VKI_MA_WRITE) 38618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot |= VKI_PROT_WRITE; 38628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mflags & VKI_MA_EXEC) 38638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot |= VKI_PROT_EXEC; 38648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_dev != VKI_PRNODEV) { 38668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->dev = map->pr_dev; 38678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->ino = map->pr_ino; 38688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->foffset = map->pr_offset; 38698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 38708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj else { 38718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->dev = 0; 38728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->ino = 0; 38738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->foffset = 0; 38748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 38758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Try to get the filename. */ 38778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->filename[0] = '\0'; 38788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mapname[0] != '\0') { 38798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_sprintf)(mapping->filename, "/proc/self/path/%s", 38808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj map->pr_mapname); 38818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Int r = ML_(am_readlink)(mapping->filename, mapping->filename, 38828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj sizeof(mapping->filename) - 1); 38838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (r == -1) { 38848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* If Valgrind is executed in a non-global zone and the link in 38858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /proc/self/path/ represents a file that is available through lofs 38868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj from a global zone then the kernel may not be able to resolve the 38878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj link. 38888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj In such a case, return a corresponding /proc/self/object/ file to 38908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj allow Valgrind to read the file if it is necessary. 38918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj This can create some discrepancy for the sanity check. For 38938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj instance, if a client program mmaps some file then the address 38948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj space manager will have a correct zone-local name of that file, 38958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj but the sanity check will receive a different file name from this 38968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj code. This currently does not represent a problem because the 38978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj sanity check ignores the file names (it uses device and inode 38988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj numbers for the comparison). 38998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */ 39008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ML_(am_sprintf)(mapping->filename, "/proc/self/object/%s", 39018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj map->pr_mapname); 39028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 39038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj else { 39048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(r >= 0); 39058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->filename[r] = '\0'; 39068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 39078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 39088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj *idx += 1; 39108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return mapping; 39118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 39128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39138eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic Mapping *next_rmap(const HChar *buffer, SizeT entries, SizeT *idx, 39148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Mapping *mapping) 39158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 39168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(idx); 39178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(mapping); 39188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (*idx >= entries) 39208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return NULL; /* No more entries */ 39218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj const vki_prmap_t *map = (const vki_prmap_t *)buffer + *idx; 39238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->addr = map->pr_vaddr; 39258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->size = map->pr_size; 39268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot = 0; 39288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mflags & VKI_MA_READ) 39298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot |= VKI_PROT_READ; 39308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mflags & VKI_MA_WRITE) 39318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot |= VKI_PROT_WRITE; 39328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (map->pr_mflags & VKI_MA_EXEC) 39338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->prot |= VKI_PROT_EXEC; 39348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->dev = 0; 39368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->ino = 0; 39378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->foffset = 0; 39388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj mapping->filename[0] = '\0'; 39398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj *idx += 1; 39418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return mapping; 39428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 39438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* Used for two purposes: 39458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 1. Establish initial mappings upon the process startup 39468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 2. Check mappings during aspacemgr sanity check 39478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */ 39488eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic void parse_procselfmaps ( 39498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj void (*record_mapping)( Addr addr, SizeT len, UInt prot, 39508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ULong dev, ULong ino, Off64T offset, 39518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj const HChar *filename ), 39528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj void (*record_gap)( Addr addr, SizeT len ) 39538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj ) 39548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 39558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Addr start = Addr_MIN; 39568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Addr gap_start = Addr_MIN; 39578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#define M_XMAP_BUF (VG_N_SEGMENTS * sizeof(vki_prxmap_t)) 39598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Static to keep it out of stack frame... */ 39608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj static HChar xmap_buf[M_XMAP_BUF]; 39618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj const Mapping *xmap = NULL; 39628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT xmap_index = 0; /* Current entry */ 39638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT xmap_entries; 39648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Mapping xmap_mapping; 39658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Bool advance_xmap; 39668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#define M_RMAP_BUF (VG_N_SEGMENTS * sizeof(vki_prmap_t)) 39688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj static HChar rmap_buf[M_RMAP_BUF]; 39698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj const Mapping *rmap = NULL; 39708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT rmap_index = 0; /* Current entry */ 39718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT rmap_entries; 39728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Mapping rmap_mapping; 39738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj Bool advance_rmap; 39748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Read fully /proc/self/xmap and /proc/self/rmap. */ 39768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj xmap_entries = read_proc_file("/proc/self/xmap", xmap_buf, M_XMAP_BUF, 39778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "M_XMAP_BUF", sizeof(vki_prxmap_t)); 39788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj rmap_entries = read_proc_file("/proc/self/rmap", rmap_buf, M_RMAP_BUF, 39808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "M_RMAP_BUF", sizeof(vki_prmap_t)); 39818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Get the first xmap and rmap. */ 39838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj advance_xmap = True; 39848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj advance_rmap = True; 39858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj while (1) { 39878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Get next xmap or rmap if necessary. */ 39888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (advance_xmap) { 39898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj xmap = next_xmap(xmap_buf, xmap_entries, &xmap_index, &xmap_mapping); 39908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj advance_xmap = False; 39918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 39928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (advance_rmap) { 39938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj rmap = next_rmap(rmap_buf, rmap_entries, &rmap_index, &rmap_mapping); 39948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj advance_rmap = False; 39958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 39968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 39978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Check if the end has been reached. */ 39988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (rmap == NULL) 39998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj break; 40008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Invariants */ 40028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (xmap != NULL) { 40038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(start <= xmap->addr); 40048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(rmap->addr <= xmap->addr); 40058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 40068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (xmap != NULL && start == xmap->addr) { 40088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* xmap mapping reached. */ 40098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(xmap->addr >= rmap->addr && 40108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj xmap->addr + xmap->size <= rmap->addr + rmap->size); 40118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj aspacem_assert(xmap->prot == rmap->prot); 40128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (record_mapping != NULL) 40148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (*record_mapping)(xmap->addr, xmap->size, xmap->prot, xmap->dev, 40158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj xmap->ino, xmap->foffset, 40168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (xmap->filename[0] != '\0') ? 40178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj xmap->filename : NULL); 40188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj start = xmap->addr + xmap->size; 40208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj advance_xmap = True; 40218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 40228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj else if (start >= rmap->addr) { 40238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Reserved-only part. */ 40248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* First calculate size until the end of this reserved mapping... */ 40258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj SizeT size = rmap->addr + rmap->size - start; 40268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* ... but shrink it if some xmap is in a way. */ 40278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (xmap != NULL && size > xmap->addr - start) 40288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj size = xmap->addr - start; 40298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (record_mapping != NULL) 40318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (*record_mapping)(start, size, rmap->prot, 0, 0, 0, NULL); 40328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj start += size; 40338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 40348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj else { 40358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Gap. */ 40368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (record_gap != NULL && gap_start < start) 40378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (*record_gap)(gap_start, start - gap_start); 40388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj start = rmap->addr; 40398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 40408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40418eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (rmap->addr + rmap->size <= start) 40428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj advance_rmap = True; 40438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj gap_start = start; 40458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 40468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (record_gap != NULL && gap_start < Addr_MAX) 40488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj (*record_gap)(gap_start, Addr_MAX - gap_start + 1); 40498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 40508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif // defined(VGO_solaris) 40528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/*------END-procmaps-parser-for-Solaris--------------------------*/ 40548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 40558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#endif // defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) 4056f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 405798abfc7bb7798c4ac4580f7e0bc7171de94a0255fitzhardinge/*--------------------------------------------------------------------*/ 4058945ed2e53f6bbe9c84a8173b63881158132d9ca8njn/*--- end ---*/ 4059de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/ 4060