1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The address space manager: segment initialisation and ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- tracking, stack operations ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Implementation for AIX5 m_aspacemgr-aix5.c ---*/ 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copyright (C) 2006-2010 OpenWorks LLP 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info@open-works.co.uk 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Neither the names of the U.S. Department of Energy nor the 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown University of California nor the names of its contributors may be 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used to endorse or promote products derived from this software 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without prior written permission. 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_aix5) 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ************************************************************* 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO NOT INCLUDE ANY OTHER FILES HERE. 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ADD NEW INCLUDES ONLY TO priv_aspacemgr.h 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AND THEN ONLY AFTER READING DIRE WARNINGS THERE TOO. 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ************************************************************* */ 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_aspacemgr.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Note: many of the exported functions implemented below are 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown described more fully in comments in pub_core_aspacemgr.h. 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This provides a minimal address space management facility for AIX5. 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It is not as comprehensive, robust or efficient as its Linux 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown counterpart. 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It does implement the advise/notify concept described in 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacemgr-linux.c, but minimally. It only keeps track of the 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mappings belonging to Valgrind; the client can do what it likes so 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long as it doesn't trash Valgrind's mappings. 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is unfortunate, but the root problem is that it is impossible 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to find out on AIX what the complete set of mappings for a process 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is. Sure, AIX does have /proc/pid/map, but it's weak compared to 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux's: it just shows some small subset of the mappings, not all 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of them. So it is not very useful: it can't be used to discover 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the true initial process mapping state, and it can't be used to 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cross-check Valgrind's internal mapping table, as is done at 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --sanity-level=3 and above on Linux. 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The Address Space Manager's state. ---*/ 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Describes AIX5-specific segment kinds */ 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum { 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkFree=1, // free space 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkMText, // module text (code) mapping 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkMData, // module data (& bss) mapping 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkFileV, // file mapping belonging to valgrind 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkAnonC, // anonymous mapping belonging to the client 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkAnonV, // anonymous mapping belonging to valgrind 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkShmemC, // shm mapping belonging to the client 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkPreAlloc // area preallocated from sbrk 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegKind; 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Segment table entries, in summary: 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkFree start end 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkMText start end r w x sibling ismainexe fname mname 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkMData start end r w x sibling 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FileV start end r w x fname offset 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AnonC start end r w x fromP isCH 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AnonV start end r w x fromP 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ShmemC start end r w x 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PreAlloc start end 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Entries are non-overlapping and cover the entire address space 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exactly (as in the Linux aspacem). Unlike Linux there are no 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alignment constraints, since we're just recording what's going on, 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rather than controlling it. 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MText/MData are XCOFF mapped modules, as determined by looking at 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /proc/../map. MText is the primary entry and contains the text 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown range. MData contains the data range, if the module has a data 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping (usually but not always). MText also holds the avma of the 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown corresponding data segment start, if any, (sibling field) so it can 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be found and the two added/removed together. Similarly MData 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown contains the address of the corresponding MText (also sibling). 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fname/mname only apply to MText. To find the fname/mname for MData 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown you have to look at the corresponding MText entry, which is 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guaranteed to exist. MText may exist without a corresponding MData 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but not vice versa. Kludge: in fact fname/mname have to be 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allowed in MData, else read_procselfmap doesn't work. 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MText may have a zero sibling pointer, indicating that there is no 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown corresponding MData. But MData must have a nonzero sibling pointer 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown since MData without MText is not allowed. Implication is that 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown neither MText nor MData may be mapped at zero as this would mess up 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the representation, but I don't think that will ever happen since 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AIX uses page zero as a readonly const-zero area. 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For MData entries, the data section size acquired from /proc/../map 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appears to also include the bss, so there is no need for any 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown further handling of that. 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isCH indicates whether an AnonC area is part of the client heap 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or not. May not be set for any other kind of area. 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown File and member names are entries into the string table. 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fromP, for AnonC/AnonV, if True, indicates that the segment was 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocated from a PreAlloc area, and so should be returned to that 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state upon deallocation. If False, indicates that the segment 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should be unmapped on deallocation. 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegKind kind; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ALL: extent */ 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: zero-length segments are not allowed. That guarantees 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that start <= end. */ 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr start; // lowest addr in range (ALL) 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr end; // highest addr in range (ALL) 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ALL except Free */ 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool hasR; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool hasW; 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool hasX; 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* misc */ 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sibling; // MText, MData only: addr of MData/MText 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isMainExe; // MText only: is this the main executable? 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isCH; // AnonC only: is this part of the client's heap? 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool fromP; // AnonC, AnonV only: originated from PreAlloc? 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* fname; // MText, FileV only: filename 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* mname; // MText only: member name if present 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Off64T offset; // FileV only: file offset 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VG_N_ASEGMENTS 5000 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg[VG_N_ASEGMENTS]; 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int used; 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegments; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ start of STATE for the address-space manager ------ */ 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A table of zero-terminated strings (file names etc). This 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is only ever added to. */ 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VG_N_ASTRTAB 200000 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int strtab_used = 0; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar strtab[VG_N_ASTRTAB]; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define Addr_MIN ((Addr)0) 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define Addr_MAX ((Addr)(-1ULL)) 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The main array of AixSegments, in order as required. */ 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AixSegments asegs_pri; 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* and two auxiliary arrays. */ 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AixSegments asegs_tnew; 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AixSegments asegs_told; 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The assumed size of the main thread's stack, so that we can add a 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment for it at startup. */ 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_FAKE_STACK_PAGES_MIN 4096 /* 16M fake stack */ /* default size */ 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_FAKE_STACK_PAGES_MAX 32768 /* 128M fake stack */ /* max size? */ 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Hacks which are probably for AIX 'millicode'. Note: ensure 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown these stay page aligned. */ 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAGIC_PAGES_1_BASE 0x3000 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAGIC_PAGES_1_SIZE (2*0x1000) 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAGIC_PAGES_2_BASE 0xC000 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAGIC_PAGES_2_SIZE (4*0x1000) 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AM_SANITY_CHECK(_who) \ 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level >= 3)) { \ 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = sane_AixSegments(&asegs_pri); \ 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) \ 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspace", "sanity check failed, " \ 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "who = %s\n", _who); \ 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ok); \ 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* When preallocating a block from sbrk-world, how much extra 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should we pre-emptively acquire? */ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define AM_PREALLOC_EXTRA (512 * 1024) 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//#define AM_PREALLOC_EXTRA 0x0800000 /* 8 M */ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AM_PREALLOC_EXTRA 0x4000000 /* 64 M */ 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The AIX5 aspacem implementation needs to be told when it is and 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown isn't allowed to use sbrk to allocate memory. Hence: */ 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_aix5_sbrk_allowed) = True; 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ end of STATE for the address-space manager ------ */ 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Forwards decls ------ */ 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_procselfmap ( /*OUT*/ AixSegments* ); 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Stuff for 4K (small-page-size) rounding. ---*/ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AM_4K_PAGESZ 4096 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool AM_IS_4K_ALIGNED ( UWord w ) 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord m = AM_4K_PAGESZ-1; 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toBool( (w & m) == 0 ); 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UWord AM_4K_ROUNDUP ( UWord w ) 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord m = AM_4K_PAGESZ-1; 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (w+m) & (~m); 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UWord AM_64K_ROUNDUP ( UWord w ) 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord m = 0x10000-1; 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (w+m) & (~m); 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- String table management. ---*/ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add the given string into the string table (or find an existing 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown copy of it) and return a pointer to the in-table version. The 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pointer will be valid for the entire rest of the run. */ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* add_to_strtab ( UChar* str ) 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int off, len; 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, look for the string. */ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown off = 0; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (off < strtab_used) { 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(str, &strtab[off])) 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &strtab[off]; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown off += VG_(strlen)(&strtab[off]) + 1; 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* not present? we'll have to copy it then. */ 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = VG_(strlen)(str); 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len + 1 + strtab_used > VG_N_ASTRTAB) 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf_toolow)("VG_N_ASTRTAB"); 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown off = strtab_used; 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (; *str; str++) 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strtab[strtab_used++] = *str; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strtab[strtab_used++] = 0; 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(strtab_used <= VG_N_ASTRTAB); 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &strtab[off]; 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_in_strtab ( UChar* str ) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (str < &strtab[0]) 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (str >= &strtab[strtab_used]) 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (str > &strtab[0] && str[-1] != 0) 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Low level AixSegment stuff. ---*/ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_AixSegment ( AixSegment* s ) 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->kind = 0; /* invalid */ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->start = 0; 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->end = 0; 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->hasR = False; 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->hasW = False; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->hasX = False; 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->sibling = 0; 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->isMainExe = False; 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->isCH = False; 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->fromP = False; 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->fname = NULL; 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->mname = NULL; 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s->offset = 0; 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* name_of_AixSegKind ( AixSegKind sk ) 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (sk) { 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFree: return "Free "; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMText: return "MText"; 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMData: return "MData"; 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonV: return "AnonV"; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonC: return "AnonC"; 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFileV: return "FileV"; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkShmemC: return "ShmC "; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkPreAlloc: return "PreAl"; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: ML_(am_barf)("name_of_AixSegKind"); 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid show_AixSegment ( Int logLevel, Int segNo, AixSegment* seg ) 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* segName = name_of_AixSegKind( seg->kind ); 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (seg->kind) { 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFree: 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: %s %010llx-%010llx\n", 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo, /*segName*/" ", 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->start, (ULong)seg->end 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMText: 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: %s %010llx-%010llx %c%c%c-- (d %010llx) %s%s%s%s\n", 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo, seg->isMainExe ? "MTEXT" : "MText", 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->start, (ULong)seg->end, 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasR ? 'r' : '-', 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasW ? 'w' : '-', 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasX ? 'x' : '-', 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->sibling, 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->fname, 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->mname ? "(" : "", 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->mname ? (HChar*)seg->mname : "", 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->mname ? ")" : "" 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMData: 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: %s %010llx-%010llx %c%c%c-- (t %010llx)\n", 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo, "MData", 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->start, (ULong)seg->end, 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasR ? 'r' : '-', 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasW ? 'w' : '-', 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasX ? 'x' : '-', 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->sibling 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFileV: 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: %s %010llx-%010llx %c%c%c-- %6lld %s\n", 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo, segName, 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->start, (ULong)seg->end, 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasR ? 'r' : '-', 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasW ? 'w' : '-', 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasX ? 'x' : '-', 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->offset, 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->fname 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonV: 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonC: 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkShmemC: 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: %s %010llx-%010llx %c%c%c%c%c\n", 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo, segName, 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->start, (ULong)seg->end, 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasR ? 'r' : '-', 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasW ? 'w' : '-', 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasX ? 'x' : '-', 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->kind==ASkAnonC && seg->isCH ? 'H' : '-', 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->fromP ? 'P' : '-' 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkPreAlloc: 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: %s %010llx-%010llx %c%c%c-- (size %llu)\n", 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo, segName, 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->start, (ULong)seg->end, 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasR ? 'r' : '-', 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasW ? 'w' : '-', 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg->hasX ? 'x' : '-', 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)seg->end - (ULong)seg->start + 1 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%3d: show_AixSegment: unknown segment\n", 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segNo); 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_AixSegments ( AixSegments* segs ) 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->used = 1; 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &segs->seg[0] ); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[0].kind = ASkFree; 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[0].start = Addr_MIN; 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[0].end = Addr_MAX; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid show_AixSegments ( Int logLevel, HChar* who, AixSegments* segs ) 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", "<<< %s\n", who); 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used; i++) 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment( logLevel, i, &segs->seg[i] ); 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(logLevel, "aspacem", ">>>\n"); 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AixSegment ( AixSegment* seg ) 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* disallow zero and negative length segments */ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->end < seg->start) 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (seg->kind) { 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFree: 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->hasR || seg->hasW || seg->hasX) 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isMainExe || seg->sibling != 0 || seg->offset != 0) 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->fname || seg->mname) 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isCH || seg->fromP) 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMText: 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_in_strtab(seg->fname)) 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->mname && !is_in_strtab(seg->mname)) 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->offset != 0) 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isCH || seg->fromP) 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMData: 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isMainExe || seg->sibling == 0 || seg->offset != 0) 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* fname/mname have to be allowed in MData, else 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read_procselfmap doesn't work. Unfortunately. */ 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->fname || seg->mname) 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isCH || seg->fromP) 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFileV: 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_in_strtab(seg->fname)) 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->mname != NULL) 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isMainExe || seg->sibling != 0) 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isCH || seg->fromP) 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkShmemC: 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonV: 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonC: 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->fname || seg->mname) 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isMainExe || seg->sibling != 0) 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->offset != 0) 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->kind != ASkAnonC && seg->isCH) 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (!(seg->kind == ASkAnonV || seg->kind == ASkAnonC)) 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && seg->fromP) 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkPreAlloc: 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->fname || seg->mname) 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->isMainExe || seg->sibling != 0) 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->offset != 0) 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->kind != ASkAnonC && seg->isCH) 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->fromP) 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!AM_IS_4K_ALIGNED(seg->start)) 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!AM_IS_4K_ALIGNED(seg->end + 1)) 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(seg->hasR && seg->hasW && seg->hasX)) 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Binary search the interval array for a given address. Since the 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown array covers the entire address space the search cannot fail. */ 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int find_asegment_idx ( AixSegments* segs, Addr a ) 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_mid_lo, a_mid_hi; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int mid, 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = 0, 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = segs->used-1; 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(lo <= hi); 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* current unsearched space is from lo to hi, inclusive. */ 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lo > hi) { 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found. This can't happen. */ 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("find_nsegment_idx: not found"); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mid = (lo + hi) / 2; 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a_mid_lo = segs->seg[mid].start; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a_mid_hi = segs->seg[mid].end; 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a < a_mid_lo) { hi = mid-1; continue; } 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a > a_mid_hi) { lo = mid+1; continue; } 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(a >= a_mid_lo && a <= a_mid_hi); 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0 <= mid && mid < segs->used); 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mid; 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AixSegments ( AixSegments* segs ) 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check endpoints */ 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->used < 1 || segs->used > VG_N_ASEGMENTS) { 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad ->used"); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[0].start != Addr_MIN 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || segs->seg[segs->used-1].end != Addr_MAX) { 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad endpoints"); 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check each segment, and check entire range is covered. */ 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used; i++) { 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sane_AixSegment( &segs->seg[i] )) { 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sane_AixSegments: bad segment %d\n", i); 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i < segs->used; i++) { 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i-1].end + 1 != segs->seg[i].start) { 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sane_AixSegments: bad transition at %d/%d\n", i-1,i); 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we know 'seg' is safe for use in find_asegment_idx(). 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Check the sibling pointers for MText/MData. 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also check that the segment starting at address zero is neither 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MText nor MData (since this would mess up the sibling pointer 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown representation; see comments above.) Failure of this is not per 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown se a logic failure, but it does indicate that the kernel 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unexpectedly placed MText or MData at zero, and our 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown representation is therefore inadequate. 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[0].kind == ASkMText || segs->seg[0].kind == ASkMData) { 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sane_AixSegments: ASkMText/ASkMData at address zero\n"); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used-1; i++) { 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment *s1, *s2; 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1 = &segs->seg[i]; 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->kind == ASkMData) { 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s2 = &segs->seg[ find_asegment_idx(segs, s1->sibling) ]; 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s2->kind != ASkMText 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || find_asegment_idx(segs, s2->sibling) != i) { 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad sibling " 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "link(s) for ASkData\n"); 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->kind == ASkMText && s1->sibling != 0) { 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s2 = &segs->seg[ find_asegment_idx(segs, s1->sibling) ]; 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s2->kind != ASkMData 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || find_asegment_idx(segs, s2->sibling) != i) { 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad sibling " 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "link(s) for ASkText\n"); 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Try merging s2 into s1, if possible. If successful, s1 is 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modified, and True is returned. Otherwise s1 is unchanged and 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False is returned. */ 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool maybe_merge_asegments ( AixSegment* s1, AixSegment* s2 ) 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->kind != s2->kind) 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->end+1 != s2->start) 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (s1->kind) { 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFree: 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1->end = s2->end; 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonC: 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonV: 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->hasR == s2->hasR && s1->hasW == s2->hasW 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && s1->hasX == s2->hasX && s1->isCH == s2->isCH 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && s1->fromP == s2->fromP) { 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1->end = s2->end; 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* not really necessary, but .. */ 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case SkFileV: 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s1->hasR == s2->hasR 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && s1->hasW == s2->hasW && s1->hasX == s2->hasX 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && s1->fname == s2->fname 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && s2->offset == s1->offset 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + ((ULong)s2->start) - ((ULong)s1->start) ) { 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1->end = s2->end; 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* it's important to merge PreAlloc's back together to avoid 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fragmenting PreAlloc'd space unnecessarily */ 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkPreAlloc: 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1->end = s2->end; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Merge mergable segments in SEGS. */ 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void preen_asegments ( AixSegments* segs ) 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int r, w; 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(segs->used >= 1); 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->used == 1) 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w = 0; 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (r = 1; r < segs->used; r++) { 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (maybe_merge_asegments(&segs->seg[w], &segs->seg[r])) { 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* nothing */ 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w++; 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (w != r) 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[w] = segs->seg[r]; 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w++; 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(w > 0 && w <= segs->used); 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->used = w; 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Modifying a segment array, and constructing segments. ---*/ 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Split the segment containing 'a' into two, so that 'a' is 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guaranteed to be the start of a new segment. If 'a' is already the 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start of a segment, do nothing. */ 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void split_asegment_at ( AixSegments* segs, Addr a ) 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, j; 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(a > 0); 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(segs->used >= 1); 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = find_asegment_idx(segs, a); 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(i >= 0 && i < segs->used); 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i].start == a) 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 'a' is already the start point of a segment, so nothing to be 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done. */ 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else we have to slide the segments upwards to make a hole */ 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->used >= VG_N_ASEGMENTS) 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf_toolow)("VG_N_ASEGMENTS"); 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = segs->used-1; j > i; j--) 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[j+1] = segs->seg[j]; 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->used++; 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i+1] = segs->seg[i]; 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i+1].start = a; 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].end = a-1; 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i].kind == ASkFileV /* || segs->seg[i].kind == ASkFileC*/) 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i+1].offset 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown += ((ULong)segs->seg[i+1].start) - ((ULong)segs->seg[i].start); 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sane_AixSegment(&segs->seg[i])); 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sane_AixSegment(&segs->seg[i+1])); 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do the minimum amount of segment splitting necessary to ensure that 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sLo is the first address denoted by some segment and sHi is the 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown highest address denoted by some other segment. Returns the indices 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the lowest and highest segments in the range. */ 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid split_asegments_lo_and_hi ( AixSegments* segs, 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sLo, Addr sHi, 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Int* iLo, 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Int* iHi ) 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sLo < sHi); 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sLo > 0) 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown split_asegment_at(segs, sLo); 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sHi < Addr_MAX) 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown split_asegment_at(segs, sHi+1); 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *iLo = find_asegment_idx(segs,sLo); 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *iHi = find_asegment_idx(segs,sHi); 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0 <= *iLo && *iLo < segs->used); 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0 <= *iHi && *iHi < segs->used); 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*iLo <= *iHi); 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(segs->seg[*iLo].start == sLo); 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(segs->seg[*iHi].end == sHi); 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not that I'm overly paranoid or anything, definitely not :-) */ 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add SEG to the collection, deleting/truncating any it overlaps. 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This deals with all the tricky cases of splitting up segments as 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown needed. Contents of SEG are copied. */ 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_asegment ( AixSegments* segs, AixSegment* seg ) 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, iLo, iHi, delta; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool segment_is_sane; 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sStart = seg->start; 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sEnd = seg->end; 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sStart <= sEnd); 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment_is_sane = sane_AixSegment(seg); 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!segment_is_sane) show_AixSegment(0,0,seg); 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(segment_is_sane); 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown split_asegments_lo_and_hi( segs, sStart, sEnd, &iLo, &iHi ); 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now iLo .. iHi inclusive is the range of segment indices which 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg will replace. If we're replacing more than one segment, 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slide those above the range down to fill the hole. */ 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delta = iHi - iLo; 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(delta >= 0); 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (delta > 0) { 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = iLo; i < segs->used-delta; i++) 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i] = segs->seg[i+delta]; 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->used -= delta; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(segs->used >= 1); 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[iLo] = *seg; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preen_asegments(segs); 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(am_show_nsegments)(0,"AFTER preen (add_segment)"); 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert everything in SEG except MData and MText into Free, 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then preen, so as to retain normalised form. */ 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void knockout_non_module_segs ( AixSegments* segs ) 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr s, e; 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used; i++) { 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i].kind == ASkFree 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || segs->seg[i].kind == ASkMText 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || segs->seg[i].kind == ASkMData) 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s = segs->seg[i].start; 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e = segs->seg[i].end; 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &segs->seg[i] ); 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].start = s; 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].end = e; 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].kind = ASkFree; 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preen_asegments(segs); 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments(segs) ); 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy a segment array. */ 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void copy_asegments_d_s ( AixSegments* dst, AixSegments* src ) 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(src->used >= 1 && src->used < VG_N_ASEGMENTS); 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->used = src->used; 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < src->used; i++) 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst->seg[i] = src->seg[i]; 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Re-reading /proc/../map and updating MText/MData segments ---*/ 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find out the size of the AixCodeSegChange that must be 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown presented to VG_(am_aix5_reread_procmap). */ 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(am_aix5_reread_procmap_howmany_directives)(void) 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In the worst imaginable case, all the tracked modules could have 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown disappeared and been replaced with different ones. Hence: */ 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 2 * VG_N_ASEGMENTS; 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid add_pri_text_and_data_segs ( AixSegment* tnew, AixSegment* dnew ) 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool dExists = (dnew->end - dnew->start + 1) != 0; 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(tnew->kind == ASkMText); 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(dnew->kind == ASkMData); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dExists) { 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(tnew->sibling == dnew->start); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(dnew->sibling == tnew->start); 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(&asegs_pri, tnew); 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(&asegs_pri, dnew); 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(tnew->sibling == 0); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(&asegs_pri, tnew); 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid del_pri_text_and_data_segs ( AixSegment* told, AixSegment* dold ) 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment fre; 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool dExists = (dold->end - dold->start + 1) != 0; 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(told->kind == ASkMText); 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(dold->kind == ASkMData); 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &fre ); 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.kind = ASkFree; 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dExists) { 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(told->sibling == dold->start); 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(dold->sibling == told->start); 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.start = told->start; 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.end = told->end; 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(&asegs_pri, &fre); 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.start = dold->start; 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.end = dold->end; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(&asegs_pri, &fre); 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(told->sibling == 0); 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.start = told->start; 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fre.end = told->end; 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(&asegs_pri, &fre); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tell aspacem that /proc/<pid>/map may have changed (eg following 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __loadx) and so it should be re-read, and the code/data segment 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown list updated accordingly. The resulting array of AixCodeChangeSeg 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown directives are written to 'directives', and the number of entries 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to *ndirectives. */ 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(am_aix5_reread_procmap) 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( /*OUT*/AixCodeSegChange* directives, /*OUT*/Int* ndirectives ) 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ixold, ixnew; 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool done_old, done_new; 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment *olds, *news; 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, read /proc/../map into asegs_tnew. Copy asegs_pri into 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_told, and remove everything except MData and MText, so as 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to generate something we can sanely compare with asegs_tnew. 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Walk asegs_told and asegs_tnew together, writing the differences 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to 'directives', and modifying asegs_pri accordingly. */ 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parse_procselfmap( &asegs_tnew ); 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown copy_asegments_d_s( &asegs_told, &asegs_pri ); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown knockout_non_module_segs( &asegs_told ); 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ndirectives = 0; 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define MODIFY_PRI(_dir, _asegs, _ixt, _acquire) \ 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int _ixd; \ 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment *_segt, *_segd; \ 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment _segd_dummy; \ 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(_ixt >= 0 && _ixt < _asegs.used); \ 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _segt = &_asegs.seg[_ixt]; \ 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(_segt->kind == ASkMText); \ 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (_segt->sibling) { \ 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _ixd = find_asegment_idx( &_asegs, _segt->sibling ); \ 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _segd = &_asegs.seg[_ixd]; \ 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(_segd->kind == ASkMData); \ 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(_segt->sibling == _segd->start); \ 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { \ 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &_segd_dummy ); \ 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _segd_dummy.kind = ASkMData; \ 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _segd_dummy.start = 1; \ 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _segd_dummy.end = 0; \ 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _segd = &_segd_dummy; \ 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (_segd != &_segd_dummy) \ 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(_segd->sibling == _segt->start); \ 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).code_start = (_segt)->start; \ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).code_len = (_segt)->end - (_segt)->start + 1; \ 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).data_start = (_segd)->start; \ 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).data_len = (_segd)->end - (_segd)->start + 1; \ 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).file_name = (_segt)->fname; \ 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).mem_name = (_segt)->mname; \ 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).is_mainexe = (_acquire) ? (_segt)->isMainExe : False; \ 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_dir).acquire = (_acquire); \ 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (_acquire) { \ 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_pri_text_and_data_segs( _segt, _segd ); \ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { \ 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown del_pri_text_and_data_segs( _segt, _segd ); \ 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixold = 0; /* indexes asegs_told */ 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixnew = 0; /* indexes asegs_tnew */ 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixold >= 0 && ixold < asegs_told.used); 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixnew >= 0 && ixnew < asegs_tnew.used); 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Advance ixold and ixnew to the next MText in their 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown respective arrays. */ 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (ixold < asegs_told.used 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && asegs_told.seg[ixold].kind != ASkMText) { 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(asegs_told.seg[ixold].kind == ASkFree 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || asegs_told.seg[ixold].kind == ASkMData); 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixold++; 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (ixnew < asegs_tnew.used 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && asegs_tnew.seg[ixnew].kind != ASkMText) { 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(asegs_tnew.seg[ixnew].kind == ASkFree 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || asegs_tnew.seg[ixnew].kind == ASkMData); 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixnew++; 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixold >= 0 && ixold <= asegs_told.used); 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixnew >= 0 && ixnew <= asegs_tnew.used); 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done_old = ixold == asegs_told.used; 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done_new = ixnew == asegs_tnew.used; 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (done_old && done_new) 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto both_done; 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (done_old && !done_new) 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto finishup_new; 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (done_new && !done_old) 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto finishup_old; 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown olds = &asegs_told.seg[ixold]; 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown news = &asegs_tnew.seg[ixnew]; 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(olds->kind == ASkMText); 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(news->kind == ASkMText); 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment(0,ixold,&asegs_told.seg[ixold]); 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment(0,ixnew,&asegs_tnew.seg[ixnew]); 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "\n"); 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Here, if olds->start < news->start, then the old sequence has 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an entry which the new one doesn't, so a module has been 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unloaded. If news->start < olds->start then the new sequence 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown has a module the old one doesn't, so a module has been 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loaded. If news->start ==olds->start then the module is 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unchanged. Except, we should check a bit more carefully in 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the zero case. */ 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (olds->start == news->start) { 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (olds->start == news->start 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && olds->end == news->end 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && olds->fname == news->fname 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && olds->mname == news->mname 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && olds->sibling == news->sibling 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && olds->isMainExe == news->isMainExe) { 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* really identical, do nothing */ 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dubious; mark it as an unload of old and load of 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new. */ 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MODIFY_PRI(directives[*ndirectives], asegs_told, ixold, False); 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*ndirectives)++; 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*ndirectives <= 2 * VG_N_ASEGMENTS); 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MODIFY_PRI(directives[*ndirectives], asegs_tnew, ixnew, True); 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*ndirectives)++; 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*ndirectives <= 2 * VG_N_ASEGMENTS); 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixold++; 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixnew++; 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (olds->start < news->start) { 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* discard olds */ 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MODIFY_PRI(directives[*ndirectives], asegs_told, ixold, False); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*ndirectives)++; 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*ndirectives <= 2 * VG_N_ASEGMENTS); 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixold++; 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (news->start < olds->start) { 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* acquire news */ 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MODIFY_PRI(directives[*ndirectives], asegs_tnew, ixnew, True); 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*ndirectives)++; 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*ndirectives <= 2 * VG_N_ASEGMENTS); 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixnew++; 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0); 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown finishup_new: 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown olds = NULL; 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixold == asegs_told.used); 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixnew < asegs_tnew.used); 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (ixnew < asegs_tnew.used) { 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown news = &asegs_tnew.seg[ixnew]; 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(news->kind == ASkMText || news->kind == ASkMData 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || news->kind == ASkFree); 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (news->kind == ASkMText) { 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MODIFY_PRI(directives[*ndirectives], asegs_tnew, ixnew, True); 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*ndirectives)++; 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*ndirectives <= 2 * VG_N_ASEGMENTS); 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixnew++; 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto both_done; 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown finishup_old: 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown news = NULL; 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixnew == asegs_tnew.used); 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixold < asegs_told.used); 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (ixold < asegs_told.used) { 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown olds = &asegs_told.seg[ixold]; 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(olds->kind == ASkMText || olds->kind == ASkMData 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || olds->kind == ASkFree); 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (olds->kind == ASkMText) { 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MODIFY_PRI(directives[*ndirectives], asegs_told, ixold, False); 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*ndirectives)++; 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(*ndirectives <= 2 * VG_N_ASEGMENTS); 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixold++; 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto both_done; 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both_done: 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixold == asegs_told.used); 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixnew == asegs_tnew.used); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_tnew.used = 0; 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_told.used = 0; 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments(&asegs_pri) ); 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef MODIFY_PRI 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the initial stack segment. Contains kludgery. Also take the 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown opportunity to create fake segs for the millicode areas. */ 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(am_aix5_set_initial_client_sp)( Addr sp ) 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool done = False; 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word n_fake_stack_pages; 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word m1 = 1048576; 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(!done); 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done = True; 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We are given the initial client SP (that of the root thread). 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Already on the stack are argv and env. How far up does it 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extend? We assume to the next 64k boundary. How far down does 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it extend? We assume N_FAKE_STACK_PAGES small pages - by 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default 16M. Establish those limits and add an AnonC rwx 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment. */ 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The 64k boundary is "justified" as follows. On 32-bit AIX 5.3, 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a typical initial SP is 0x2FF22xxx, but the accessible (rw) area 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown beyond that extends up to 0x2FF2FFFF - the next 64k boundary. 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In 64-bit mode, a typical initial SP might be 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xFFF'FFFF'FFFF'E920, and the accessible area extends to 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xFFF'FFFF'FFFF'FFFF. So in both cases, (64k roundup of sp) - 1 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown gives the end of the accessible area. */ 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"aspacem", "aix5_set_initial_client_sp( %p )\n", 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)sp); 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonC; 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = seg.hasW = seg.hasX = True; 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(void*) == 4 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ((sp & 0xFFFF0000) == 0x2FF20000 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (sp & 0xFFFF0000) == 0x2FF10000)) { 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Gaaah. Special-case 32-bit mode. */ 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = 0x2FF2FFFF; 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = AM_64K_ROUNDUP(sp) - 1; 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_fake_stack_pages = N_FAKE_STACK_PAGES_MIN; 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_main_stacksize) > 0 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && ((m1+VG_(clo_main_stacksize)) / VKI_PAGE_SIZE) > n_fake_stack_pages) { 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_fake_stack_pages = (m1+VG_(clo_main_stacksize)) / VKI_PAGE_SIZE; 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n_fake_stack_pages > N_FAKE_STACK_PAGES_MAX) { 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Allocation of the stack failed. We have to stop. */ 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)( 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, "aspacem", 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "valgrind: " 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "I failed to allocate space for the application's stack.\n"); 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)( 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, "aspacem", 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "valgrind: " 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "This may be the result of a very large --max-stackframe=\n"); 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)( 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, "aspacem", 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "valgrind: " 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "setting. Cannot continue. Sorry.\n\n"); 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_exit)(0); 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = seg.end+1 - n_fake_stack_pages * VKI_PAGE_SIZE; 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"aspacem", "aix5_set_initial_client_sp: stack seg:\n"); 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment(1,0, &seg); 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonC; 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = seg.hasX = True; 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = MAGIC_PAGES_1_BASE; 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = MAGIC_PAGES_1_BASE + MAGIC_PAGES_1_SIZE - 1; 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"aspacem", "am_aix5_set_initial_client_sp: FAKE1 seg:\n"); 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment(1,0, &seg); 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonC; 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = seg.hasX = True; 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = MAGIC_PAGES_2_BASE; 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = MAGIC_PAGES_2_BASE + MAGIC_PAGES_2_SIZE - 1; 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"aspacem", "am_aix5_set_initial_client_sp: FAKE2 seg:\n"); 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment(1,0, &seg); 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Getting segment-starts. ---*/ 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Print out the segment array (debugging only!). */ 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(am_show_nsegments) ( Int logLevel, HChar* who ) 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegments( logLevel, who, &asegs_pri ); 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get the filename corresponding to this segment, if known and if it 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown has one. The returned name's storage cannot be assumed to be 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown persistent, so the caller should immediately copy the name 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown elsewhere. On AIX5, we don't know what this is (in general) 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so just return NULL. */ 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(am_get_filename)( NSegment const* seg ) 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Collect up the start addresses of all non-free, non-resvn segments. 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The interface is a bit strange in order to avoid potential 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment-creation races caused by dynamic allocation of the result 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buffer *starts. 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The function first computes how many entries in the result 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buffer *starts will be needed. If this number <= nStarts, 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they are placed in starts[0..], and the number is returned. 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If nStarts is not large enough, nothing is written to 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown starts[0..], and the negation of the size is returned. 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Correct use of this function may mean calling it multiple times in 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown order to establish a suitably-sized buffer. */ 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(am_get_segment_starts)( Addr* starts, Int nStarts ) 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, j, nSegs; 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* don't pass dumbass arguments */ 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(nStarts >= 0); 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nSegs = 0; 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < asegs_pri.used; i++) { 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (asegs_pri.seg[i].kind == ASkFree 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || asegs_pri.seg[i].kind == ASkPreAlloc) 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nSegs++; 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nSegs > nStarts) { 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The buffer isn't big enough. Tell the caller how big it needs 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to be. */ 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -nSegs; 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's enough space. So write into the result buffer. */ 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(nSegs <= nStarts); 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < asegs_pri.used; i++) { 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (asegs_pri.seg[i].kind == ASkFree 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || asegs_pri.seg[i].kind == ASkPreAlloc) 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown starts[j++] = asegs_pri.seg[i].start; 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(j == nSegs); /* this should not fail */ 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return nSegs; 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Sanity checking and preening of the segment array. ---*/ 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_do_sync_check) ( const HChar* fn, 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar* file, Int line ) 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's nothing we can do here; just return a dummy value. */ 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* placate gcc */ 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Hook to allow sanity checks to be done from aspacemgr-common.c. */ 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(am_do_sanity_check)( void ) 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = sane_AixSegments( &asegs_pri ); 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ok); 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Finding segments. ---*/ 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Finds the segment containing 'a'. Only returns file/anon/resvn 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segments. On AIX5 this is pretty bogus; we fake up an entry as 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown best we can by snooping round for useful information in 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_pri. */ 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownNSegment const* VG_(am_find_nsegment) ( Addr a ) 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment* aseg; 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static NSegment bogus; 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fill in default info. */ 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkAnonC; 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.start = 0; 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.end = 0; 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.smode = SmFixed; 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.dev = 0; 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.ino = 0; 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.mode = 0; 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.offset = 0; 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.fnIdx = -1; 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = bogus.hasW = bogus.hasX = False; 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasT = False; 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.isCH = False; 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.mark = False; 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Go look for it in the segment table. */ 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = find_asegment_idx( &asegs_pri, a ); 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(i >= 0 && i <= asegs_pri.used); 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aseg = &asegs_pri.seg[i]; 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aseg->kind == ASkFree || aseg->kind == ASkPreAlloc) 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.start = aseg->start; 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.end = aseg->end; 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Refine */ 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (aseg->kind) { 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMText: 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkAnonC; /* hmm, pretty darn bogus */ 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = bogus.hasX = True; 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkMData: 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkAnonC; /* hmm, pretty darn bogus */ 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = bogus.hasW = True; 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkShmemC: 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkShmC; 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = aseg->hasR; 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasW = aseg->hasW; 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasX = aseg->hasX; 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonC: 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkAnonC; 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = aseg->hasR; 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasW = aseg->hasW; 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasX = aseg->hasX; 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.isCH = aseg->isCH; 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkAnonV: 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkAnonV; 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = aseg->hasR; 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasW = aseg->hasW; 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasX = aseg->hasX; 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ASkFileV: 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.kind = SkFileV; 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasR = aseg->hasR; 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasW = aseg->hasW; 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.hasX = aseg->hasX; 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bogus.offset = aseg->offset; 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0); 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return &bogus; 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the next segment along from 'here', if it is a file/anon/resvn 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment. */ 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownNSegment const* VG_(am_next_nsegment) ( NSegment* here, Bool fwds ) 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_next_nsegment)"); 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; /* placate gcc */ 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Trivial fn: return the total amount of space in anonymous mappings, 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both for V and the client. Is used for printing stats in 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out-of-memory messages. */ 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong VG_(am_get_anonsize_total)( void ) 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong total = 0; 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < asegs_pri.used; i++) { 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (asegs_pri.seg[i].kind == ASkAnonC 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || asegs_pri.seg[i].kind == ASkAnonV) { 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown total += (ULong)asegs_pri.seg[i].end 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (ULong)asegs_pri.seg[i].start + 1ULL; 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return total; 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Test if a piece of memory is addressable by the client with at 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown least the "prot" protection permissions by examining the underlying 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segments. */ 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_is_valid_for_client)( Addr start, SizeT len, 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt prot ) 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const * const fake = VG_(am_find_nsegment)(start); 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!fake) 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(fake->start <= start); 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(start + len - 1 <= fake->end); 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fake->kind == SkAnonV || fake->kind == SkFileV) 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((prot & VKI_PROT_READ) && !fake->hasR) 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((prot & VKI_PROT_WRITE) && !fake->hasW) 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((prot & VKI_PROT_EXEC) && !fake->hasX) 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Variant of VG_(am_is_valid_for_client) which allows free areas to 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be considered part of the client's addressable space. It also 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown considers reservations to be allowable, since from the client's 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point of view they don't exist. */ 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_is_valid_for_client_or_free_or_resvn) 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( Addr start, SizeT len, UInt prot ) 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: " 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(am_is_valid_for_client_or_free_or_resvn)"); 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Startup, including reading /proc/self/maps. ---*/ 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the address space manager, setting up the initial 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment list, and reading /proc/self/maps into it. This must 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be called before any other function. 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Takes a pointer to the SP at the time V gained control. This is 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown taken to be the highest usable address (more or less). Based on 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that (and general consultation of tea leaves, etc) return a 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown suggested end address for the client's stack. */ 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(am_startup) ( Addr sp_at_startup ) 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sizeof(Word) == sizeof(void*)); 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sizeof(Addr) == sizeof(void*)); 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sizeof(SizeT) == sizeof(void*)); 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sizeof(SSizeT) == sizeof(void*)); 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_tnew.used = 0; 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_told.used = 0; 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_pri.used = 1; 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegments( &asegs_pri ); 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments(&asegs_pri) ); 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_show_nsegments)(0,"AFTER VG_(am_startup)"); 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We do not make an initial read of /proc/../map since doing so 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would leave us without a way to communicate the results to a 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller. Hence we expect that the caller (m_main) will call 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_aix5_reread_procmap) soon after this call so as to get 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the initial code/data segments recorded. */ 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Return value is irrelevant since we don't lay out the 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client's stack; it is already done. */ 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Preallocation (acquiring space from sbrk). ---*/ 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes local_do_sbrk_NO_NOTIFY( Word delta ) 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(__NR_AIX5_sbrk != __NR_AIX5_UNKNOWN); 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall1)(__NR_AIX5_sbrk, (UWord)delta); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* kernel produces (-1, VKI_ENOMEM) on failure. I think that's 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok. */ 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the ix of a prealloc section containing at least req_sz bytes, 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or -1 if not found. Uses best-fit. */ 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int find_prealloc_idx ( SizeT req_sz ) 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT best_sz, this_sz; 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int best_ix, i; 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sizeof(SizeT) == sizeof(Addr)); 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(req_sz > 0); 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(AM_IS_4K_ALIGNED(req_sz)); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown best_sz = Addr_MAX; 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown best_ix = -1; 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < asegs_pri.used; i++) { 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment* s = &asegs_pri.seg[i]; 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s->kind != ASkPreAlloc) 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this_sz 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = s->end + 1 - s->start; 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(this_sz > 0); 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(AM_IS_4K_ALIGNED(this_sz)); 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (this_sz >= req_sz && this_sz < best_sz) { 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown best_sz = this_sz; 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown best_ix = i; 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return best_ix; 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a new prealloc section containing req_sz bytes. Returns 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False if failed, True on success. */ 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool new_prealloc ( SizeT req_sz ) 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr start; 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSizeT delta; 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* why = NULL; 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(req_sz > 0); 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(AM_IS_4K_ALIGNED(req_sz)); 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* m_syswrap may have decided that it's not currently safe to allow 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocations from sbrk-world. If so, we have to fail. */ 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && !VG_(am_aix5_sbrk_allowed)) { 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why = "sbrk disallowed"; 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto fail; 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the current limit. */ 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = local_do_sbrk_NO_NOTIFY(0); 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sres.isError) { 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why = "initial sbrk failed"; 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto fail; 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get it page aligned */ 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delta = AM_4K_ROUNDUP(sres.res) - sres.res; 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(delta >= 0 && delta < AM_4K_PAGESZ); 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (delta > 0) { 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = local_do_sbrk_NO_NOTIFY(delta); 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sres.isError) { 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why = "aligning sbrk failed"; 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto fail; 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now the brk is aligned. Try to acquire the block. */ 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = local_do_sbrk_NO_NOTIFY(0); 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sres.isError) 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start = sres.res; 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( AM_IS_4K_ALIGNED( start )); 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = local_do_sbrk_NO_NOTIFY( req_sz ); 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sres.isError) { 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why = "main sbrk failed"; 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto fail; 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this fails, the kernel is acting strange. */ 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sres.res == start ); 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = start; 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = start + req_sz - 1; 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkPreAlloc; 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = seg.hasW = seg.hasX = True; /* presumably */ 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)( 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1, "aspacem", "new_prealloc: SUCCESS at 0x%llx size %lld\n", 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)start, (ULong)req_sz 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fail: 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "aspacem", "new_prealloc: FAILED: %s\n", why); 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the ix of a prealloc section capable of holding a block of 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size req_sz. If none exists, try to create one first. Returns -1 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown on failure. */ 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int find_or_create_prealloc_idx ( SizeT req_sz ) 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ix; 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT req_szX; 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool alloc_ok; 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "zz", " find_or_create_prealloc_idx ( %lu )\n", 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown req_sz); 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sizeof(SizeT) == sizeof(Addr)); 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(req_sz > 0); 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(AM_IS_4K_ALIGNED(req_sz)); 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ix = find_prealloc_idx ( req_sz ); 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ix >= 0 && ix < asegs_pri.used) 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ix; 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found. We'll have to allocate one. Allocate some extra at 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same time, so as to give a reservoir from which to satisfy 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown future requests. */ 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ix == -1); 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown req_szX = req_sz + AM_PREALLOC_EXTRA; 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(req_szX > 0); 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(AM_IS_4K_ALIGNED(req_szX)); 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alloc_ok = new_prealloc( req_szX ); 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!alloc_ok) 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; /* failed */ 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We should now be able to find it in the segment table. */ 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ix = find_prealloc_idx( req_sz ); 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ix >= 0 && ix < asegs_pri.used); 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ix; 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The core query-notify mechanism. ---*/ 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Query aspacem to ask where a mapping should go. */ 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(am_get_advisory) ( MapRequest* req, 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool forClient, 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Bool* ok ) 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_get_advisory)"); 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; /* placate gcc -Wall */ 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convenience wrapper for VG_(am_get_advisory) for client floating or 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fixed requests. If start is zero, a floating request is issued; if 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nonzero, a fixed request at that address is issued. Same comments 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown about return values apply. */ 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(am_get_advisory_client_simple) ( Addr start, SizeT len, 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*OUT*/Bool* ok ) 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_get_advisory_client_simple)"); 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; /* placate gcc -Wall */ 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notifies aspacem that the client completed an mmap successfully. 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The segment array is updated accordingly. If the returned Bool is 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True, the caller should immediately discard translations from the 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specified address range. */ 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags, 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fd, Off64T offset ) 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool needDiscard; 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Discard is needed if any of the just-trashed range had T. */ 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown needDiscard = True; /* conservative but safe */ 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonC; /* XXX bogus: could be a file */ 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = a; 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = a + len - 1; 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = toBool(prot & VKI_PROT_READ); 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasW = toBool(prot & VKI_PROT_WRITE); 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasX = toBool(prot & VKI_PROT_EXEC); 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspacem","notify mmap ( %p, %ld, %ld, %ld )\n", 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a, len, (UWord)prot, (UWord)flags); 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AM_SANITY_CHECK("am_notify_client_mmap"); 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return needDiscard; 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notifies aspacem that the client completed a shmat successfully. 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The segment array is updated accordingly. If the returned Bool is 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True, the caller should immediately discard translations from the 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specified address range. */ 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ) 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkShmemC; 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = a; 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = seg.start + len - 1; 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = (prot & VKI_PROT_READ) ? True : False; 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasW = (prot & VKI_PROT_WRITE) ? True : False; 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasX = (prot & VKI_PROT_EXEC) ? True : False; 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AM_SANITY_CHECK("am_notify_client_shmat"); 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(am_show_nsegments)(0, "after shmat"); 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; /* be paranoid */ 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notifies aspacem that an mprotect was completed successfully. The 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment array is updated accordingly. Note, as with 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_notify_munmap), it is not the job of this function to reject 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stupid mprotects, for example the client doing mprotect of 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-client areas. Such requests should be intercepted earlier, by 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the syscall wrapper for mprotect. This function merely records 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whatever it is told. If the returned Bool is True, the caller 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should immediately discard translations from the specified address 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown range. */ 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot ) 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, iLo, iHi; 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool newR, newW, newX, needDiscard; 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newR = toBool(prot & VKI_PROT_READ); 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newW = toBool(prot & VKI_PROT_WRITE); 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newX = toBool(prot & VKI_PROT_EXEC); 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Discard is needed if we're dumping X permission */ 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown needDiscard = True; /* conservative but correct */ 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown split_asegments_lo_and_hi( &asegs_pri, start, start+len-1, &iLo, &iHi ); 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iLo = find_asegment_idx(&asegs_pri, start); 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iHi = find_asegment_idx(&asegs_pri, start + len - 1); 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = iLo; i <= iHi; i++) { 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(i >= 0 && i < asegs_pri.used); 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Apply the permissions to all relevant segments. */ 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (asegs_pri.seg[i].kind != ASkFree) { 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_pri.seg[i].hasR = newR; 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_pri.seg[i].hasW = newW; 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_pri.seg[i].hasX = newX; 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(sane_AixSegment(&asegs_pri.seg[i])); 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspacem","notify mprotect ( %p, %ld, %ld )\n", 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)start, len, (UWord)prot); 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Changing permissions could have made previously un-mergable 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segments mergeable. Therefore have to re-preen them. */ 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown preen_asegments(&asegs_pri); 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AM_SANITY_CHECK("am_notify_mprotect"); 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return needDiscard; 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notifies aspacem that an munmap completed successfully. The 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment array is updated accordingly. As with 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_notify_munmap), we merely record the given info, and don't 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check it for sensibleness. If the returned Bool is True, the 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller should immediately discard translations from the specified 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address range. */ 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_notify_munmap)( Addr start, SizeT len ) 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool needDiscard = True; /* conservative but safe */ 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkFree; 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = start; 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = start + len - 1; 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AM_SANITY_CHECK("am_notify_munmap"); 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return needDiscard; 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Handling mappings which do not arise directly from the ---*/ 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- simulation of the client. ---*/ 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- --- map, unmap, protect --- --- --- */ 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a file at a fixed address for the client, and update the 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment array accordingly. */ 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_mmap_file_fixed_client) 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset ) 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes r = {0,0}; 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_mmap_file_fixed_client)"); 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map anonymously at a fixed address for the client, and update 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the segment array accordingly. */ 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_mmap_anon_fixed_client) ( Addr start, SizeT length, UInt prot ) 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes r = {0,0}; 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_mmap_anon_fixed_client)"); 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map anonymously at an unconstrained address for the client, and 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown update the segment array accordingly. */ 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot ) 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not allowable. */ 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (length == 0) 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* AIX seems to demand fd == -1 in anonymous mappings. hence: */ 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_do_mmap_NO_NOTIFY)( 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, length, 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prot, 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -1, 0 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sres.isError) { 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonC; 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = sres.res; 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = seg.start + length - 1; 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = toBool((prot & VKI_PROT_READ) > 0); 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasW = toBool((prot & VKI_PROT_WRITE) > 0); 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasX = toBool((prot & VKI_PROT_EXEC) > 0); 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.fromP = False; 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "aspacem", "new AnonC from mmap, size %lu\n", 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown length ); 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, acquire new address space for the client but with 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown considerable restrictions on what can be done with it: (1) the 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actual protections may exceed those stated in 'prot', (2) the 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown area's protections cannot be later changed using any form of 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mprotect, and (3) the area cannot be freed using any form of 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown munmap. On Linux this behaves the same as 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_mmap_anon_float_client). On AIX5 this *may* allocate memory 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by using sbrk, so as to make use of large pages on AIX. */ 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_sbrk_anon_float_client) ( SizeT length, Int prot ) 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ix; 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT lenX = AM_4K_ROUNDUP(length); 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not allowable. */ 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (length == 0) 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First see if we can get space from sbrk-world. */ 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ix = find_or_create_prealloc_idx ( lenX ); 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ix >= 0 && ix < asegs_pri.used) { 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonC; 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = asegs_pri.seg[ix].start; 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = seg.start + lenX - 1; 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = toBool((prot & VKI_PROT_READ) > 0); 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasW = toBool((prot & VKI_PROT_WRITE) > 0); 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasX = toBool((prot & VKI_PROT_EXEC) > 0); 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.fromP = True; 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(mk_SysRes_Success)( seg.start ); 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "aspacem", "new AnonC from prealloc, size %lu\n", 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown length ); 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* That didn't work out. Try mmap-world instead. */ 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ix == -1); 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(am_mmap_anon_float_client)( length, prot ); 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map anonymously at an unconstrained address for V, and update the 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment array accordingly. This is fundamentally how V allocates 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown itself more address space when needed. */ 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not allowable. */ 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (length == 0) 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* AIX seems to demand fd == -1 in anonymous mappings. hence: */ 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_do_mmap_NO_NOTIFY)( 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, length, 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -1, 0 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sres.isError) { 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonV; 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = sres.res; 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = seg.start + length - 1; 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = seg.hasW = seg.hasX = True; 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.fromP = False; 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "aspacem", "new AnonV from mmap, size %lu\n", 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown length ); 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same comments apply as per VG_(am_sbrk_anon_float_client). On 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux this behaves the same as VG_(am_mmap_anon_float_valgrind). */ 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_sbrk_anon_float_valgrind)( SizeT length ) 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ix; 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT lenX = AM_4K_ROUNDUP(length); 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not allowable. */ 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (length == 0) 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First see if we can get space from sbrk-world. */ 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ix = find_or_create_prealloc_idx ( lenX ); 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ix >= 0 && ix < asegs_pri.used) { 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = ASkAnonV; 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = asegs_pri.seg[ix].start; 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = seg.start + lenX - 1; 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = True; 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasW = True; 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasX = True; 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.fromP = True; 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(mk_SysRes_Success)( seg.start ); 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(2, "aspacem", "new AnonV from prealloc, size %lu\n", 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown length ); 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* That didn't work out. Try mmap-world instead. */ 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ix == -1); 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(am_mmap_anon_float_valgrind)( length ); 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Really just a wrapper around VG_(am_sbrk_anon_float_valgrind). */ 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(am_shadow_alloc)(SizeT size) 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres = VG_(am_sbrk_anon_float_valgrind)( size ); 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres.isError ? NULL : (void*)sres.res; 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Map a file at an unconstrained address for V, and update the 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment array accordingly. This is used by V for transiently 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping in object files to read their debug info. */ 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_mmap_file_float_valgrind) ( SizeT length, UInt prot, 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fd, Off64T offset ) 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not allowable. */ 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (length == 0 || !VG_IS_PAGE_ALIGNED(offset)) 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(am_do_mmap_NO_NOTIFY)( 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, length, 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prot, VKI_MAP_PRIVATE, 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd, offset 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sres.isError) { 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg; 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg ); 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.kind = SkFileV; 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.start = sres.res; 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.end = seg.start + length - 1; 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasR = toBool(prot & VKI_PROT_READ); 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasW = toBool(prot & VKI_PROT_WRITE); 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.hasX = toBool(prot & VKI_PROT_EXEC); 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg.fname = add_to_strtab("(FileV-float, unknown name)"); 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg ); 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments( &asegs_pri )); 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sres; 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Unmap the given address range and update the segment array 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accordingly. This fails if the range isn't valid for the client. 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If *need_discard is True after a successful return, the caller 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should immediately discard translations from the specified address 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown range. */ 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard, 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr start, SizeT len ) 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes r = {0,0}; 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_munmap_client)"); 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Unmap the given address range and update the segment array 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accordingly. This fails if the range isn't valid for valgrind. */ 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Also, if the specified range doesn't fall within a single segment, 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it barfs. This simplifies the implementation; we shouldn't need to 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deal with anything but the simplest cases. */ 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(am_munmap_valgrind)( Addr start, SizeT len ) 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment* seg; 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment seg2; 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr end; 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ixS, ixE; 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool debug = False; 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspacem", 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "am_munmap_valgrind(%p, %lu)\n", (void*)start, len); 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)(0); 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We have to be a bit careful here. If the area being unmapped is 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AnonV which originated from a preallocated area (hence from 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sbrk-land) then we will have to return it to the preallocated 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state, rather than unmapping it. */ 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end = start + len - 1; 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(start <= end); // else have wraparound?! 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixS = find_asegment_idx( &asegs_pri, start ); 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ixE = find_asegment_idx( &asegs_pri, end ); 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixS >= 0 && ixS < asegs_pri.used); 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixE >= 0 && ixE < asegs_pri.used); 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Preconditions: See comment at start of fn */ 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(ixS == ixE); 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For the segment S denoted by ixS: 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if S is AnonV from prealloc and S entirely within start .. end, 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return it to prealloc 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if S is AnonV not from prealloc and S entirely within start .. end, 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown munmap it 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if S is FileV and S entirely within start .. end, munmap it 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Otherwise, leave it alone (too complex to handle). In theory 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this could cause a leak; in practice I don't think it will. 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg = &asegs_pri.seg[ixS]; 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegment( 0, ixS, seg ); 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Invariants */ 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(seg->start <= start); 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(end <= seg->end); 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->kind == ASkFileV 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (seg->kind == ASkAnonV && (!seg->fromP))) { 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspacem", "am_munmap_valgrind: !fromP: %p-%p\n", 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)start, (void*)end); 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = ML_(am_do_munmap_NO_NOTIFY)( start, len ); 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sres.isError) 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg2 ); 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.start = start; 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.end = end; 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.kind = ASkFree; 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg2 ); 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg->kind == ASkAnonV && seg->fromP) { 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (debug) 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspacem", "am_munmap_valgrind: fromP: %p-%p\n", 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)start, (void*)end); 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment( &seg2 ); 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.start = start; 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.end = end; 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.kind = ASkPreAlloc; 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seg2.hasR = seg2.hasW = seg2.hasX = True; 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment( &asegs_pri, &seg2 ); 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shouldn't be asked to handle any other cases */ 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0); 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments( &asegs_pri )); 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Success)(0); 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad: 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments( &asegs_pri )); 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)(VKI_EINVAL); 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let (start,len) denote an area within a single Valgrind-owned 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment (anon or file). Change the ownership of [start, start+len) 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to the client instead. Fails if (start,len) does not denote a 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown suitable segment. */ 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len ) 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 'seg' must be NULL or have been obtained from 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_find_nsegment), and still valid. If non-NULL, and if it 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown denotes a SkAnonC (anonymous client mapping) area, set the .isCH 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (is-client-heap) flag for that area. Otherwise do nothing. 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Bizarre interface so that the same code works for both Linux and 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AIX and does not impose inefficiencies on the Linux version.) */ 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* AIX: presumably this is a faked-up segment our VG_(am_find_segment) 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown came up with. So we have to find the corresponding AixSegment. */ 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(am_set_segment_isCH_if_SkAnonC)( NSegment* seg ) 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (seg == NULL) 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = find_asegment_idx( &asegs_pri, seg->start ); 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(i >= 0 && i < asegs_pri.used ); 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (asegs_pri.seg[i].kind == ASkAnonC) { 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asegs_pri.seg[i].isCH = True; 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"aspacem","set isCH for %p\n", (void*)seg->start ); 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(asegs_pri.seg[i].isCH == False); 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment. */ 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* AIX: we ignore these complexities by conservatively assuming that 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all segments had translations taken from them. Hence we can safely 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ignore this. */ 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( NSegment* seg ) 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- --- reservations --- --- --- */ 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a reservation from START .. START+LENGTH-1, with the given 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ShrinkMode. When checking whether the reservation can be created, 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown also ensure that at least abs(EXTRA) extra free bytes will remain 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown above (> 0) or below (< 0) the reservation. 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The reservation will only be created if it, plus the extra-zone, 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown falls entirely within a single free segment. The returned Bool 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicates whether the creation succeeded. */ 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_create_reservation) ( Addr start, SizeT length, 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ShrinkMode smode, SSizeT extra ) 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_create_reservation)"); 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let SEG be an anonymous client mapping. This fn extends the 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping by DELTA bytes, taking the space from a reservation section 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which must be adjacent. If DELTA is positive, the segment is 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extended forwards in the address space, and the reservation must be 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the next one along. If DELTA is negative, the segment is extended 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown backwards in the address space and the reservation must be the 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown previous one. DELTA must be page aligned. abs(DELTA) must not 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exceed the size of the reservation segment minus one page, that is, 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the reservation segment after the operation must be at least one 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown page long. */ 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_extend_into_adjacent_reservation_client) ( NSegment* seg, 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SSizeT delta ) 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: " 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(am_extend_into_adjacent_reservation_client)"); 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- --- resizing/move a mapping --- --- --- */ 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let SEG be a client mapping (anonymous or file). This fn extends 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the mapping forwards only by DELTA bytes, and trashes whatever was 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the new area. Fails if SEG is not a single client mapping or if 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the new area is not accessible to the client. Fails if DELTA is 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not page aligned. *seg is invalid after a successful return. If 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *need_discard is True after a successful return, the caller should 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown immediately discard translations from the new area. */ 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard, 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment* seg, SizeT delta ) 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_extend_map_client)"); 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Remap the old address range to the new address range. Fails if any 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parameter is not page aligned, if the either size is zero, if any 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wraparound is implied, if the old address range does not fall 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entirely within a single segment, if the new address range overlaps 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with the old one, or if the old address range is not a valid client 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapping. If *need_discard is True after a successful return, the 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller should immediately discard translations from both specified 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address ranges. */ 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr old_addr, SizeT old_len, 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr new_addr, SizeT new_len ) 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("unimplemented: VG_(am_relocate_nooverlap_client)"); 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- A simple parser for /proc/<pid>/map on AIX5. ---*/ 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Almost completely independent of the stuff above. The ---*/ 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- only function it 'exports' to the code above this comment ---*/ 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- is parse_procselfmaps. ---*/ 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-----------------------------------------------------------------*/ 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/procfs.h> 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Size of a smallish table used to read /proc/<pid>/map entries. */ 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define M_APROCMAP_BUF 100000 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* static ... to keep it out of the stack frame. */ 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar procmap_buf[M_APROCMAP_BUF]; 2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Records length of /proc/<pid>/map read into procmap_buf. */ 2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int buf_n_tot; 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper fns. */ 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get the contents of /proc/<pid>/map into a static buffer. If 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown there's a syntax error, it won't fit, or other failure, just 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown abort. */ 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void read_procselfmap_into_buf ( void ) 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char fname[50]; 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_chunk; 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes fd; 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_sprintf)( fname, "/proc/%d/map", ML_(am_getpid)() ); 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Read the initial memory mapping from the /proc filesystem. */ 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd = ML_(am_open)( fname, VKI_O_RDONLY, 0 ); 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fd.isError) 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("can't open /proc/<pid>/map"); 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_n_tot = 0; 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_chunk = ML_(am_read)( fd.res, &procmap_buf[buf_n_tot], 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M_APROCMAP_BUF - buf_n_tot ); 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf_n_tot += n_chunk; 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while ( n_chunk > 0 && buf_n_tot < M_APROCMAP_BUF ); 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_close)(fd.res); 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (buf_n_tot >= M_APROCMAP_BUF-5) 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf_toolow)("M_APROCMAP_BUF"); 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (buf_n_tot == 0) 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_barf)("I/O error on /proc/<pid>/map"); 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown procmap_buf[buf_n_tot] = 0; 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* /proc/<pid>/map appears to give out a non-absolute path name for 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the main executable. Fortunately we can reliably identify the main 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable via the MA_MAINEXEC bit, and if we find the path is 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-absolute, replace it with /proc/<pid>/object/a.out instead. 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AIX guarantees the latter is another name for the main 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable. */ 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* kludge_exe_file_name ( HChar* file_name, prmap_t* map ) 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Int my_pid = -1; 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static HChar a_out_name[64]; 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (file_name == NULL) 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (file_name[0] != '/' && (map->pr_mflags & MA_MAINEXEC)) { 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (my_pid == -1) 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown my_pid = ML_(am_getpid)(); 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(am_sprintf)(a_out_name, "/proc/%d/object/a.out", my_pid); 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_name = a_out_name; 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return file_name; 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Parse /proc/<pid>/map, copying the entries in it into an 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegments structure. Returns a properly formed AixSegments, with 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkMText/ASkMData entries, with sibling pointers set up, and 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ASkFree everywhere else. 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void parse_procselfmap ( /*OUT*/AixSegments* segs ) 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar rr, ww, xx, mm, ss; 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prmap_t* map; 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* file_name; 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* member_name; 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool show_map; 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int off, i, j; 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AixSegment s; 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const UInt valid_pr_mflags 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = MA_MAINEXEC | MA_KERNTEXT | MA_READ | MA_WRITE 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | MA_EXEC | MA_SHARED | MA_BREAK | MA_STACK; 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->used = 1; 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegments(segs); 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments(segs) ); 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read_procselfmap_into_buf(); 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "procselfmaps", "got %d bytes\n", buf_n_tot); 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown off = 0; 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stay sane .. */ 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (off + sizeof(prmap_t) > buf_n_tot) 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown map = (prmap_t*)&procmap_buf[off]; 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown off += sizeof(prmap_t); 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* When should we stop reading the array? 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /usr/include/sys/procfs.h says that "Array entries continue 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown until an entry with a pr_size field of 0 and invalid 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pr_mflags occurs." It unhelpfully fails to define what 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "invalid" means here. However, the following test _seems_ to 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown work. */ 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map->pr_size == 0 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (map->pr_mflags & valid_pr_mflags) == 0) 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, keep going, but ignore any zero-sized mappings: */ 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map->pr_size == 0) 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mm = (map->pr_mflags & MA_MAINEXEC) > 0; 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rr = (map->pr_mflags & MA_READ) > 0; 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ww = (map->pr_mflags & MA_WRITE) > 0; 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xx = (map->pr_mflags & MA_EXEC) > 0; 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ss = (map->pr_mflags & MA_SHARED) > 0; 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map->pr_pathoff > 0) { 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_name = &procmap_buf[map->pr_pathoff]; 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown member_name = file_name + VG_(strlen)(file_name) + 1; 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*member_name == 0) 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown member_name = NULL; 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_name = member_name = NULL; 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_name = kludge_exe_file_name( file_name, map ); 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now file_name and member_name are NULL or ordinary strings. 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Convert them to string-table resident strings. */ 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (file_name) 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_name = add_to_strtab(file_name); 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (member_name) 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown member_name = add_to_strtab(member_name); 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create a suitable kind of segment. Initially we will start 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with bogus sibling pointers, and allow ASkMData entries to 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have file names, since we cannot assume anything about the 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ordering of entries in the procmap file. In a second pass, 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we will set up the sibling pointers based on those file 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown names, then remove the MData file names. */ 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_AixSegment(&s); 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_map = False; 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (rr && (!ww) && xx) { 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map->pr_size > 0) { 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* r-x segment; add bounds for a text area. */ 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.kind = ASkMText; 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.start = (Addr)map->pr_vaddr; 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.end = (Addr)map->pr_vaddr + (Addr)map->pr_size - 1; 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.isMainExe = mm; 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.sibling = 0; 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.fname = file_name; 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.mname = member_name; 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.hasR = rr; 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.hasW = ww; 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.hasX = xx; 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(segs, &s); 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (rr && ww && (!xx)) { 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (map->pr_size > 0) { 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* rw- segment; add bounds for a data area. */ 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.kind = ASkMData; 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.start = (Addr)map->pr_vaddr; 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.end = (Addr)map->pr_vaddr + (Addr)map->pr_size - 1; 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set a bogus non-zero sibling pointer, since sanity 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown checking will reject zero sibling pointers on MData. 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It doesn't matter since the loops following this one 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown below fix up the sibling pointers. */ 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.sibling = 1; 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.fname = file_name; 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.mname = member_name; 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.hasR = rr; 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.hasW = ww; 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s.hasX = xx; 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_asegment(segs, &s); 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unclassifiable; we better complain. */ 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_map = True; 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "parse_procselfmap: unclassifiable:\n"); 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show_map) 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"aspacem", 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " %010llx-%010llx %c%c%c%c%c %s%s%s%s\n", 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)map->pr_vaddr, 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)map->pr_vaddr + (ULong)map->pr_size, 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mm ? 'M' : '-', 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rr ? 'r' : '-', 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ww ? 'w' : '-', 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xx ? 'x' : '-', 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ss ? 'S' : '-', 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file_name ? file_name : (UChar*)"(none)", 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown member_name ? "(" : "", 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown member_name ? member_name : (UChar*)"", 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown member_name ? ")" : "" 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up sibling pointers. For each MData, find an MText with the 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same file/member names, or complain. This is really ugly in 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that it makes the process quadratic in the number of modules 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mapped in, but I can't think of a (simple) better way. */ 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used; i++) { 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i].kind != ASkMData) 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < segs->used; j++) { 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[j].kind == ASkMText 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && segs->seg[j].fname == segs->seg[i].fname 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && segs->seg[j].mname == segs->seg[i].mname) 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j == segs->used) { 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "parse_procselfmap: " 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "data segment with no associated text segment:\n"); 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0, "aspacem", "module = %s(%s)\n", 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].fname, 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].mname ? segs->seg[i].mname 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : (UChar*)"(none)"); 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(0); 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(j >= 0 && j < segs->used && j != i); 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].sibling = segs->seg[j].start; 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* (Almost) dually, for each MText, find an MData with same 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file/member names, but don't complain if not present. */ 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used; i++) { 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i].kind != ASkMText) 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < segs->used; j++) { 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[j].kind == ASkMData 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && segs->seg[j].fname == segs->seg[i].fname 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && segs->seg[j].mname == segs->seg[i].mname) 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j == segs->used) { 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no corresponding MData found; harmless. */ 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert(j >= 0 && j < segs->used && j != i); 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].sibling = segs->seg[j].start; 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finally, get rid of fname/mname pointers on MDatas, so as to 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown adhere to the necessary representational invariants. */ 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < segs->used; i++) { 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (segs->seg[i].kind == ASkMData){ 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segs->seg[i].fname = segs->seg[i].mname = NULL; 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aspacem_assert( sane_AixSegments(segs) ); 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_AixSegments(0, "as read from procmap", segs); 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGO_aix5) 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2645