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