h_main.c revision 024598e40c84666cc311a42c256bbf880db3ac99
1024598e40c84666cc311a42c256bbf880db3ac99sewardj
2024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Ptrcheck: a pointer-use checker.                             ---*/
4024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- This file checks heap accesses.                              ---*/
5024598e40c84666cc311a42c256bbf880db3ac99sewardj/*---                                                     h_main.c ---*/
6024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
7024598e40c84666cc311a42c256bbf880db3ac99sewardj
8024598e40c84666cc311a42c256bbf880db3ac99sewardj/*
9024598e40c84666cc311a42c256bbf880db3ac99sewardj   This file is part of Ptrcheck, a Valgrind tool for checking pointer
10024598e40c84666cc311a42c256bbf880db3ac99sewardj   use in programs.
11024598e40c84666cc311a42c256bbf880db3ac99sewardj
12024598e40c84666cc311a42c256bbf880db3ac99sewardj   Initial version (Annelid):
13024598e40c84666cc311a42c256bbf880db3ac99sewardj
14024598e40c84666cc311a42c256bbf880db3ac99sewardj   Copyright (C) 2003-2008 Nicholas Nethercote
15024598e40c84666cc311a42c256bbf880db3ac99sewardj      njn@valgrind.org
16024598e40c84666cc311a42c256bbf880db3ac99sewardj
17024598e40c84666cc311a42c256bbf880db3ac99sewardj   Valgrind-3.X port:
18024598e40c84666cc311a42c256bbf880db3ac99sewardj
19024598e40c84666cc311a42c256bbf880db3ac99sewardj   Copyright (C) 2008-2008 OpenWorks Ltd
20024598e40c84666cc311a42c256bbf880db3ac99sewardj      info@open-works.co.uk
21024598e40c84666cc311a42c256bbf880db3ac99sewardj
22024598e40c84666cc311a42c256bbf880db3ac99sewardj   This program is free software; you can redistribute it and/or
23024598e40c84666cc311a42c256bbf880db3ac99sewardj   modify it under the terms of the GNU General Public License as
24024598e40c84666cc311a42c256bbf880db3ac99sewardj   published by the Free Software Foundation; either version 2 of the
25024598e40c84666cc311a42c256bbf880db3ac99sewardj   License, or (at your option) any later version.
26024598e40c84666cc311a42c256bbf880db3ac99sewardj
27024598e40c84666cc311a42c256bbf880db3ac99sewardj   This program is distributed in the hope that it will be useful, but
28024598e40c84666cc311a42c256bbf880db3ac99sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
29024598e40c84666cc311a42c256bbf880db3ac99sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30024598e40c84666cc311a42c256bbf880db3ac99sewardj   General Public License for more details.
31024598e40c84666cc311a42c256bbf880db3ac99sewardj
32024598e40c84666cc311a42c256bbf880db3ac99sewardj   You should have received a copy of the GNU General Public License
33024598e40c84666cc311a42c256bbf880db3ac99sewardj   along with this program; if not, write to the Free Software
34024598e40c84666cc311a42c256bbf880db3ac99sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
35024598e40c84666cc311a42c256bbf880db3ac99sewardj   02111-1307, USA.
36024598e40c84666cc311a42c256bbf880db3ac99sewardj
37024598e40c84666cc311a42c256bbf880db3ac99sewardj   The GNU General Public License is contained in the file COPYING.
38024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
39024598e40c84666cc311a42c256bbf880db3ac99sewardj
40024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: 64-bit cleanness, check the following
41024598e40c84666cc311a42c256bbf880db3ac99sewardj// struct _ISNode.ownerCount is 32-bit
42024598e40c84666cc311a42c256bbf880db3ac99sewardj// struct _ISNode.topLevel is 32-bit
43024598e40c84666cc311a42c256bbf880db3ac99sewardj// or is that not really right now?  add assertion checks about
44024598e40c84666cc311a42c256bbf880db3ac99sewardj// the max size of a node
45024598e40c84666cc311a42c256bbf880db3ac99sewardj
46024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: should we shadow %RIP?  Maybe not.
47024598e40c84666cc311a42c256bbf880db3ac99sewardj
48024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: shadows of temporaries created in preamble, a la memcheck?
49024598e40c84666cc311a42c256bbf880db3ac99sewardj
50024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: result of add_new_segment is always ignored
51024598e40c84666cc311a42c256bbf880db3ac99sewardj
52024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: the mechanism involving last_seg_added is really ugly.
53024598e40c84666cc311a42c256bbf880db3ac99sewardj// Do something cleaner.
54024598e40c84666cc311a42c256bbf880db3ac99sewardj
55024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: post_reg_write_clientcall: check function pointer comparisons
56024598e40c84666cc311a42c256bbf880db3ac99sewardj// are safe on toc-afflicted platforms
57024598e40c84666cc311a42c256bbf880db3ac99sewardj
58024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: tidy up findShadowTmp
59024598e40c84666cc311a42c256bbf880db3ac99sewardj
60024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: post_reg_write_demux(Vg_CoreSysCall) is redundant w.r.t.
61024598e40c84666cc311a42c256bbf880db3ac99sewardj// the default 'NONPTR' behaviour of post_syscall.  post_reg_write_demux
62024598e40c84666cc311a42c256bbf880db3ac99sewardj// is called first, then post_syscall.
63024598e40c84666cc311a42c256bbf880db3ac99sewardj
64024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: check nothing is mapped in the lowest 1M of memory at
65024598e40c84666cc311a42c256bbf880db3ac99sewardj// startup, or quit (to do with nonptr_or_unknown, also sync 1M
66024598e40c84666cc311a42c256bbf880db3ac99sewardj// magic value with PIE default load address in m_ume.c.
67024598e40c84666cc311a42c256bbf880db3ac99sewardj
68024598e40c84666cc311a42c256bbf880db3ac99sewardj// FIXME: consider whether we could paint memory acquired from
69024598e40c84666cc311a42c256bbf880db3ac99sewardj// sys_read etc as NONPTR rather than UNKNOWN.
70024598e40c84666cc311a42c256bbf880db3ac99sewardj
71024598e40c84666cc311a42c256bbf880db3ac99sewardj// XXX: recycle freed segments
72024598e40c84666cc311a42c256bbf880db3ac99sewardj
73024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
74024598e40c84666cc311a42c256bbf880db3ac99sewardj// Metadata:
75024598e40c84666cc311a42c256bbf880db3ac99sewardj//   HeapBlock.id :: Seg (stored as heap shadowchunk; always non-zero)
76024598e40c84666cc311a42c256bbf880db3ac99sewardj//   MemLoc.aseg  :: Seg (implicitly stored)
77024598e40c84666cc311a42c256bbf880db3ac99sewardj//   MemLoc.vseg  :: Seg (explicitly stored as the shadow memory)
78024598e40c84666cc311a42c256bbf880db3ac99sewardj//   RegLoc.vseg  :: Seg (explicitly stored as shadow registers)
79024598e40c84666cc311a42c256bbf880db3ac99sewardj//
80024598e40c84666cc311a42c256bbf880db3ac99sewardj// A Seg is made when new memory is created, eg. with malloc() or mmap().
81024598e40c84666cc311a42c256bbf880db3ac99sewardj// There are two other Segs:
82024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - NONPTR:  for something that's definitely not a pointer
83024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - UNKNOWN: for something that could be a pointer
84024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - BOTTOM:  used with pointer differences (see below)
85024598e40c84666cc311a42c256bbf880db3ac99sewardj//
86024598e40c84666cc311a42c256bbf880db3ac99sewardj// MemLoc.vseg is done at word granularity.  If a pointer is written
87024598e40c84666cc311a42c256bbf880db3ac99sewardj// to memory misaligned, the information about it will be lost -- it's
88024598e40c84666cc311a42c256bbf880db3ac99sewardj// treated as two sub-word writes to two adjacent words.  This avoids
89024598e40c84666cc311a42c256bbf880db3ac99sewardj// certain nasty cases that could arise if we tried to track unaligned
90024598e40c84666cc311a42c256bbf880db3ac99sewardj// pointers.  Fortunately, misalignment is rare so we don't lose much
91024598e40c84666cc311a42c256bbf880db3ac99sewardj// information this way.
92024598e40c84666cc311a42c256bbf880db3ac99sewardj//
93024598e40c84666cc311a42c256bbf880db3ac99sewardj// MemLoc.aseg is done at byte granularity, and *implicitly* -- ie. not
94024598e40c84666cc311a42c256bbf880db3ac99sewardj// directly accessible like MemLoc.vseg, but only by searching through all
95024598e40c84666cc311a42c256bbf880db3ac99sewardj// the segments.  Fortunately, it's mostly checked at LOADs/STOREs;  at that
96024598e40c84666cc311a42c256bbf880db3ac99sewardj// point we have a pointer p to the MemLoc m as the other arg of the
97024598e40c84666cc311a42c256bbf880db3ac99sewardj// LOAD/STORE, so we can check to see if the p.vseg's range includes m.  If
98024598e40c84666cc311a42c256bbf880db3ac99sewardj// not, it's an error and we have to search through all segments to find out
99024598e40c84666cc311a42c256bbf880db3ac99sewardj// what m.aseg really is.  That's still pretty fast though, thanks to the
100024598e40c84666cc311a42c256bbf880db3ac99sewardj// interval skip-list used.  With syscalls we must also do the skip-list
101024598e40c84666cc311a42c256bbf880db3ac99sewardj// search, but only on the first and last bytes touched.
102024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
103024598e40c84666cc311a42c256bbf880db3ac99sewardj
104024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
105024598e40c84666cc311a42c256bbf880db3ac99sewardj// Assumptions, etc:
106024598e40c84666cc311a42c256bbf880db3ac99sewardj// - see comment at top of SK_(instrument)() for how sub-word ops are
107024598e40c84666cc311a42c256bbf880db3ac99sewardj//   handled.
108024598e40c84666cc311a42c256bbf880db3ac99sewardj//
109024598e40c84666cc311a42c256bbf880db3ac99sewardj// - ioctl(), socketcall() (and ipc() will be) assumed to return non-pointers
110024598e40c84666cc311a42c256bbf880db3ac99sewardj//
111024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU_W is assumed to never write pointers.
112024598e40c84666cc311a42c256bbf880db3ac99sewardj//
113024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Assuming none of the post_mem_writes create segments worth tracking.
114024598e40c84666cc311a42c256bbf880db3ac99sewardj//
115024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Treating mmap'd segments (all! including code) like heap segments.  But
116024598e40c84666cc311a42c256bbf880db3ac99sewardj//   their ranges can change, new ones can be created by unmapping parts of
117024598e40c84666cc311a42c256bbf880db3ac99sewardj//   old segments, etc.  But this nasty behaviour seems to never happen --
118024598e40c84666cc311a42c256bbf880db3ac99sewardj//   there are assertions checking it.
119024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
120024598e40c84666cc311a42c256bbf880db3ac99sewardj
121024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
122024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am checking:
123024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Type errors:
124024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ADD, OR, LEA2: error if two pointer inputs.
125024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ADC, SBB: error if one or two pointer inputs.
126024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * AND, OR: error if two unequal pointer inputs.
127024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * NEG: error if pointer input.
128024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * {,i}mul_32_64 if either input is a pointer.
129024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * shldl/shrdl, bsf/bsr if any inputs are pointers.
130024598e40c84666cc311a42c256bbf880db3ac99sewardj//
131024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LOAD, STORE:
132024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ptr.vseg must match ptee.aseg.
133024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * ptee.aseg must not be a freed segment.
134024598e40c84666cc311a42c256bbf880db3ac99sewardj//
135024598e40c84666cc311a42c256bbf880db3ac99sewardj// - syscalls: for those accessing memory, look at first and last bytes:
136024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * check first.aseg == last.aseg
137024598e40c84666cc311a42c256bbf880db3ac99sewardj//    * check first.aseg and last.aseg are not freed segments.
138024598e40c84666cc311a42c256bbf880db3ac99sewardj//
139024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking, that I expected to when I started:
140024598e40c84666cc311a42c256bbf880db3ac99sewardj// - AND, XOR: allowing two pointers to be used if both from the same segment,
141024598e40c84666cc311a42c256bbf880db3ac99sewardj//   because "xor %r,%r" is commonly used to zero %r, and "test %r,%r"
142024598e40c84666cc311a42c256bbf880db3ac99sewardj//   (which is translated with an AND) is common too.
143024598e40c84666cc311a42c256bbf880db3ac99sewardj//
144024598e40c84666cc311a42c256bbf880db3ac99sewardj// - div_64_32/idiv_64_32 can take pointer inputs for the dividend;
145024598e40c84666cc311a42c256bbf880db3ac99sewardj//   division doesn't make sense, but modulo does, and they're done with the
146024598e40c84666cc311a42c256bbf880db3ac99sewardj//   same instruction.  (Could try to be super-clever and watch the outputs
147024598e40c84666cc311a42c256bbf880db3ac99sewardj//   to see if the quotient is used, but not worth it.)
148024598e40c84666cc311a42c256bbf880db3ac99sewardj//
149024598e40c84666cc311a42c256bbf880db3ac99sewardj// - mul_64_32/imul_64_32 can take pointers inputs for one arg or the
150024598e40c84666cc311a42c256bbf880db3ac99sewardj//   other, but not both.  This is because some programs (eg. Mozilla
151024598e40c84666cc311a42c256bbf880db3ac99sewardj//   Firebird) multiply pointers in hash routines.
152024598e40c84666cc311a42c256bbf880db3ac99sewardj//
153024598e40c84666cc311a42c256bbf880db3ac99sewardj// - NEG: can take a pointer.  It happens in glibc in a few places.  I've
154024598e40c84666cc311a42c256bbf880db3ac99sewardj//   seen the code, didn't understand it, but it's done deliberately.
155024598e40c84666cc311a42c256bbf880db3ac99sewardj//
156024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking/doing, but could, but it would require more
157024598e40c84666cc311a42c256bbf880db3ac99sewardj// instrumentation and/or slow things down a bit:
158024598e40c84666cc311a42c256bbf880db3ac99sewardj// - SUB: when differencing two pointers, result is BOTTOM, ie. "don't
159024598e40c84666cc311a42c256bbf880db3ac99sewardj//   check".  Could link segments instead, slower but a bit more accurate.
160024598e40c84666cc311a42c256bbf880db3ac99sewardj//   Also use BOTTOM when doing (ptr - unknown), which could be a pointer
161024598e40c84666cc311a42c256bbf880db3ac99sewardj//   difference with a stack/static pointer.
162024598e40c84666cc311a42c256bbf880db3ac99sewardj//
163024598e40c84666cc311a42c256bbf880db3ac99sewardj// - PUTF: input should be non-pointer
164024598e40c84666cc311a42c256bbf880db3ac99sewardj//
165024598e40c84666cc311a42c256bbf880db3ac99sewardj// - arithmetic error messages: eg. for adding two pointers, just giving the
166024598e40c84666cc311a42c256bbf880db3ac99sewardj//   segments, not the actual pointers.
167024598e40c84666cc311a42c256bbf880db3ac99sewardj//
168024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking, and would be difficult:
169024598e40c84666cc311a42c256bbf880db3ac99sewardj// - mmap(...MAP_FIXED...) is not handled specially.  It might be used in
170024598e40c84666cc311a42c256bbf880db3ac99sewardj//   ways that fool Ptrcheck into giving false positives.
171024598e40c84666cc311a42c256bbf880db3ac99sewardj//
172024598e40c84666cc311a42c256bbf880db3ac99sewardj// - syscalls: for those accessing memory, not checking that the asegs of the
173024598e40c84666cc311a42c256bbf880db3ac99sewardj//   accessed words match the vseg of the accessing pointer, because the
174024598e40c84666cc311a42c256bbf880db3ac99sewardj//   vseg is not easily accessible at the required time (would required
175024598e40c84666cc311a42c256bbf880db3ac99sewardj//   knowing for every syscall which register each arg came in, and looking
176024598e40c84666cc311a42c256bbf880db3ac99sewardj//   there).
177024598e40c84666cc311a42c256bbf880db3ac99sewardj//
178024598e40c84666cc311a42c256bbf880db3ac99sewardj// What I am not checking, and would be difficult, but doesn't matter:
179024598e40c84666cc311a42c256bbf880db3ac99sewardj// - free(p): similar to syscalls, not checking that the p.vseg matches the
180024598e40c84666cc311a42c256bbf880db3ac99sewardj//   aseg of the first byte in the block.  However, Memcheck does an
181024598e40c84666cc311a42c256bbf880db3ac99sewardj//   equivalent "bad free" check using shadow_chunks;  indeed, Ptrcheck could
182024598e40c84666cc311a42c256bbf880db3ac99sewardj//   do the same check, but there's no point duplicating functionality.  So
183024598e40c84666cc311a42c256bbf880db3ac99sewardj//   no loss, really.
184024598e40c84666cc311a42c256bbf880db3ac99sewardj//
185024598e40c84666cc311a42c256bbf880db3ac99sewardj// Other:
186024598e40c84666cc311a42c256bbf880db3ac99sewardj// - not doing anything with mprotect();  probably not worth the effort.
187024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
188024598e40c84666cc311a42c256bbf880db3ac99sewardj
189024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
190024598e40c84666cc311a42c256bbf880db3ac99sewardj// Todo:
191024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Segments for stack frames.  Would detect (some, large) stack
192024598e40c84666cc311a42c256bbf880db3ac99sewardj//   over/under-runs, dangling pointers.
193024598e40c84666cc311a42c256bbf880db3ac99sewardj//
194024598e40c84666cc311a42c256bbf880db3ac99sewardj// - Segments for static data.  Would detect over/under-runs.  Requires
195024598e40c84666cc311a42c256bbf880db3ac99sewardj//   reading debug info.
196024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
197024598e40c84666cc311a42c256bbf880db3ac99sewardj
198024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
199024598e40c84666cc311a42c256bbf880db3ac99sewardj// Some profiling results:
200024598e40c84666cc311a42c256bbf880db3ac99sewardj//                                                 twolf   konq    date sz
201024598e40c84666cc311a42c256bbf880db3ac99sewardj// 1. started                                              35.0s   14.7
202024598e40c84666cc311a42c256bbf880db3ac99sewardj// 2. introduced GETV/PUTV                                 30.2s   10.1
203024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3. inlined check_load_or_store                  5.6s    27.5s   10.1
204024598e40c84666cc311a42c256bbf880db3ac99sewardj// 4. (made check_load, check_store4 regparm(0))          (27.9s) (11.0)
205024598e40c84666cc311a42c256bbf880db3ac99sewardj// 5. um, not sure                                 5.3s    27.3s   10.6
206024598e40c84666cc311a42c256bbf880db3ac99sewardj//    ...
207024598e40c84666cc311a42c256bbf880db3ac99sewardj// 6. after big changes, corrections              11.2s    32.8s   14.0
208024598e40c84666cc311a42c256bbf880db3ac99sewardj// 7. removed link-segment chasing in check/L/S    8.9s    30.8s   14.0
209024598e40c84666cc311a42c256bbf880db3ac99sewardj// 8. avoiding do_lea1 if k is a nonptr            8.0s    28.0s   12.9
210024598e40c84666cc311a42c256bbf880db3ac99sewardj//--------------------------------------------------------------
211024598e40c84666cc311a42c256bbf880db3ac99sewardj
212024598e40c84666cc311a42c256bbf880db3ac99sewardj//#include "vg_skin.h"
213024598e40c84666cc311a42c256bbf880db3ac99sewardj
214024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_basics.h"
215024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_libcbase.h"
216024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_libcprint.h"
217024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_libcassert.h"
218024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_mallocfree.h"
219024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_execontext.h"
220024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_hashtable.h"
221024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_tooliface.h"
222024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_replacemalloc.h"
223024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_options.h"
224024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_execontext.h"
225024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_aspacemgr.h"    // VG_(am_shadow_malloc)
226024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_vki.h"          // VKI_MAX_PAGE_SIZE
227024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_machine.h"      // VG_({get,set}_shadow_regs_area) et al
228024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_debuginfo.h"    // VG_(get_fnname)
229024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_threadstate.h"  // VG_(get_running_tid)
230024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_oset.h"
231024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_vkiscnums.h"
232024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_machine.h"
233024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_wordfm.h"
234024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_xarray.h"
235024598e40c84666cc311a42c256bbf880db3ac99sewardj
236024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pc_common.h"
237024598e40c84666cc311a42c256bbf880db3ac99sewardj
238024598e40c84666cc311a42c256bbf880db3ac99sewardj//#include "h_list.h"
239024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "h_main.h"
240024598e40c84666cc311a42c256bbf880db3ac99sewardj
241024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "sg_main.h"   // sg_instrument_*, and struct _SGEnv
242024598e40c84666cc311a42c256bbf880db3ac99sewardj
243024598e40c84666cc311a42c256bbf880db3ac99sewardj
244024598e40c84666cc311a42c256bbf880db3ac99sewardj
245024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
246024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Debug/trace options                                  ---*/
247024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
248024598e40c84666cc311a42c256bbf880db3ac99sewardj
249024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Set to 1 to do sanity checks on Seg values in many places, which
250024598e40c84666cc311a42c256bbf880db3ac99sewardj   checks if bogus Segs are in circulation.  Quite expensive from a
251024598e40c84666cc311a42c256bbf880db3ac99sewardj   performance point of view. */
252024598e40c84666cc311a42c256bbf880db3ac99sewardj#define SC_SEGS 0
253024598e40c84666cc311a42c256bbf880db3ac99sewardj
254024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__client_mallocs = 0;
255024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__client_frees   = 0;
256024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__segs_allocd    = 0;
257024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__segs_recycled  = 0;
258024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__slow_searches  = 0;
259024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__slow_totcmps   = 0;
260024598e40c84666cc311a42c256bbf880db3ac99sewardj
261024598e40c84666cc311a42c256bbf880db3ac99sewardj
262024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
263024598e40c84666cc311a42c256bbf880db3ac99sewardj//                                                          //
264024598e40c84666cc311a42c256bbf880db3ac99sewardj// Segments low level storage                               //
265024598e40c84666cc311a42c256bbf880db3ac99sewardj//                                                          //
266024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
267024598e40c84666cc311a42c256bbf880db3ac99sewardj
268024598e40c84666cc311a42c256bbf880db3ac99sewardj// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since
269024598e40c84666cc311a42c256bbf880db3ac99sewardj// pc_common.c needs to see them, for error processing
270024598e40c84666cc311a42c256bbf880db3ac99sewardj
271024598e40c84666cc311a42c256bbf880db3ac99sewardj// we only start recycling segs when this many exist
272024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_FREED_SEGS (1 * 1000 * 1000)
273024598e40c84666cc311a42c256bbf880db3ac99sewardj
274024598e40c84666cc311a42c256bbf880db3ac99sewardjstruct _Seg {
275024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr  addr;
276024598e40c84666cc311a42c256bbf880db3ac99sewardj   SizeT szB; /* may be zero */
277024598e40c84666cc311a42c256bbf880db3ac99sewardj   ExeContext* ec;  /* where malloc'd or freed */
278024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* When 1, indicates block is in use.  Otherwise, used to form a
279024598e40c84666cc311a42c256bbf880db3ac99sewardj      linked list of freed blocks, running from oldest freed block to
280024598e40c84666cc311a42c256bbf880db3ac99sewardj      the most recently freed block. */
281024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _Seg* nextfree;
282024598e40c84666cc311a42c256bbf880db3ac99sewardj};
283024598e40c84666cc311a42c256bbf880db3ac99sewardj
284024598e40c84666cc311a42c256bbf880db3ac99sewardj// Determines if 'a' is before, within, or after seg's range.  Sets 'cmp' to
285024598e40c84666cc311a42c256bbf880db3ac99sewardj// -1/0/1 accordingly.  Sets 'n' to the number of bytes before/within/after.
286024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n)
287024598e40c84666cc311a42c256bbf880db3ac99sewardj{
288024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (a < seg->addr) {
289024598e40c84666cc311a42c256bbf880db3ac99sewardj      *cmp = -1;
290024598e40c84666cc311a42c256bbf880db3ac99sewardj      *n   = seg->addr - a;
291024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (a < seg->addr + seg->szB && seg->szB > 0) {
292024598e40c84666cc311a42c256bbf880db3ac99sewardj      *cmp = 0;
293024598e40c84666cc311a42c256bbf880db3ac99sewardj      *n = a - seg->addr;
294024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
295024598e40c84666cc311a42c256bbf880db3ac99sewardj      *cmp = 1;
296024598e40c84666cc311a42c256bbf880db3ac99sewardj      *n = a - (seg->addr + seg->szB);
297024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
298024598e40c84666cc311a42c256bbf880db3ac99sewardj}
299024598e40c84666cc311a42c256bbf880db3ac99sewardj
300024598e40c84666cc311a42c256bbf880db3ac99sewardjinline Bool Seg__is_freed(Seg* seg)
301024598e40c84666cc311a42c256bbf880db3ac99sewardj{
302024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!is_known_segment(seg))
303024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
304024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
305024598e40c84666cc311a42c256bbf880db3ac99sewardj      return seg->nextfree != (Seg*)1;
306024598e40c84666cc311a42c256bbf880db3ac99sewardj}
307024598e40c84666cc311a42c256bbf880db3ac99sewardj
308024598e40c84666cc311a42c256bbf880db3ac99sewardjExeContext* Seg__where(Seg* seg)
309024598e40c84666cc311a42c256bbf880db3ac99sewardj{
310024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(is_known_segment(seg));
311024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg->ec;
312024598e40c84666cc311a42c256bbf880db3ac99sewardj}
313024598e40c84666cc311a42c256bbf880db3ac99sewardj
314024598e40c84666cc311a42c256bbf880db3ac99sewardjSizeT Seg__size(Seg* seg)
315024598e40c84666cc311a42c256bbf880db3ac99sewardj{
316024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(is_known_segment(seg));
317024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg->szB;
318024598e40c84666cc311a42c256bbf880db3ac99sewardj}
319024598e40c84666cc311a42c256bbf880db3ac99sewardj
320024598e40c84666cc311a42c256bbf880db3ac99sewardjAddr Seg__addr(Seg* seg)
321024598e40c84666cc311a42c256bbf880db3ac99sewardj{
322024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(is_known_segment(seg));
323024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg->addr;
324024598e40c84666cc311a42c256bbf880db3ac99sewardj}
325024598e40c84666cc311a42c256bbf880db3ac99sewardj
326024598e40c84666cc311a42c256bbf880db3ac99sewardj
327024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_SEGS_PER_GROUP 10000
328024598e40c84666cc311a42c256bbf880db3ac99sewardj
329024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
330024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _SegGroup {
331024598e40c84666cc311a42c256bbf880db3ac99sewardj      struct _SegGroup* admin;
332024598e40c84666cc311a42c256bbf880db3ac99sewardj      UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */
333024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg segs[N_SEGS_PER_GROUP];
334024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
335024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup;
336024598e40c84666cc311a42c256bbf880db3ac99sewardj
337024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SegGroup* group_list = NULL;
338024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UWord     nFreeSegs = 0;
339024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg*      freesegs_youngest = NULL;
340024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg*      freesegs_oldest = NULL;
341024598e40c84666cc311a42c256bbf880db3ac99sewardj
342024598e40c84666cc311a42c256bbf880db3ac99sewardj
343024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SegGroup* new_SegGroup ( void ) {
344024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup));
345024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)(g, 0, sizeof(*g));
346024598e40c84666cc311a42c256bbf880db3ac99sewardj   return g;
347024598e40c84666cc311a42c256bbf880db3ac99sewardj}
348024598e40c84666cc311a42c256bbf880db3ac99sewardj
349024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Get a completely new Seg */
350024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* new_Seg ( void )
351024598e40c84666cc311a42c256bbf880db3ac99sewardj{
352024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg*      teg;
353024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup* g;
354024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (group_list == NULL) {
355024598e40c84666cc311a42c256bbf880db3ac99sewardj      g = new_SegGroup();
356024598e40c84666cc311a42c256bbf880db3ac99sewardj      g->admin = NULL;
357024598e40c84666cc311a42c256bbf880db3ac99sewardj      group_list = g;
358024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
359024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP);
360024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (group_list->nextfree == N_SEGS_PER_GROUP) {
361024598e40c84666cc311a42c256bbf880db3ac99sewardj      g = new_SegGroup();
362024598e40c84666cc311a42c256bbf880db3ac99sewardj      g->admin = group_list;
363024598e40c84666cc311a42c256bbf880db3ac99sewardj      group_list = g;
364024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
365024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(group_list->nextfree < N_SEGS_PER_GROUP);
366024598e40c84666cc311a42c256bbf880db3ac99sewardj   teg = &group_list->segs[ group_list->nextfree ];
367024598e40c84666cc311a42c256bbf880db3ac99sewardj   group_list->nextfree++;
368024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__segs_allocd++;
369024598e40c84666cc311a42c256bbf880db3ac99sewardj   return teg;
370024598e40c84666cc311a42c256bbf880db3ac99sewardj}
371024598e40c84666cc311a42c256bbf880db3ac99sewardj
372024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* get_Seg_for_malloc ( void )
373024598e40c84666cc311a42c256bbf880db3ac99sewardj{
374024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg;
375024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (nFreeSegs < N_FREED_SEGS) {
376024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg = new_Seg();
377024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg->nextfree = (Seg*)1;
378024598e40c84666cc311a42c256bbf880db3ac99sewardj      return seg;
379024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
380024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* else recycle the oldest Seg in the free list */
381024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(freesegs_youngest);
382024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(freesegs_oldest);
383024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(freesegs_youngest != freesegs_oldest);
384024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg = freesegs_oldest;
385024598e40c84666cc311a42c256bbf880db3ac99sewardj   freesegs_oldest = seg->nextfree;
386024598e40c84666cc311a42c256bbf880db3ac99sewardj   nFreeSegs--;
387024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->nextfree = (Seg*)1;
388024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__segs_recycled++;
389024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg;
390024598e40c84666cc311a42c256bbf880db3ac99sewardj}
391024598e40c84666cc311a42c256bbf880db3ac99sewardj
392024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void set_Seg_freed ( Seg* seg )
393024598e40c84666cc311a42c256bbf880db3ac99sewardj{
394024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(seg);
395024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!Seg__is_freed(seg));
396024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (nFreeSegs == 0) {
397024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_oldest == NULL);
398024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_youngest == NULL);
399024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg->nextfree = NULL;
400024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_youngest = seg;
401024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_oldest = seg;
402024598e40c84666cc311a42c256bbf880db3ac99sewardj      nFreeSegs++;
403024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
404024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_youngest);
405024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_oldest);
406024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (nFreeSegs == 1) {
407024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(freesegs_youngest == freesegs_oldest);
408024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
409024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(freesegs_youngest != freesegs_oldest);
410024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
411024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(freesegs_youngest->nextfree == NULL);
412024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(seg != freesegs_youngest && seg != freesegs_oldest);
413024598e40c84666cc311a42c256bbf880db3ac99sewardj      seg->nextfree = NULL;
414024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_youngest->nextfree = seg;
415024598e40c84666cc311a42c256bbf880db3ac99sewardj      freesegs_youngest = seg;
416024598e40c84666cc311a42c256bbf880db3ac99sewardj      nFreeSegs++;
417024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
418024598e40c84666cc311a42c256bbf880db3ac99sewardj}
419024598e40c84666cc311a42c256bbf880db3ac99sewardj
420024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic WordFM* addr_to_seg_map = NULL;
421024598e40c84666cc311a42c256bbf880db3ac99sewardj
422024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void addr_to_seg_map_ENSURE_INIT ( void )
423024598e40c84666cc311a42c256bbf880db3ac99sewardj{
424024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (UNLIKELY(addr_to_seg_map == NULL)) {
425024598e40c84666cc311a42c256bbf880db3ac99sewardj      addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1",
426024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(free), NULL );
427024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
428024598e40c84666cc311a42c256bbf880db3ac99sewardj}
429024598e40c84666cc311a42c256bbf880db3ac99sewardj
430024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* find_Seg_by_addr ( Addr ga )
431024598e40c84666cc311a42c256bbf880db3ac99sewardj{
432024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord keyW, valW;
433024598e40c84666cc311a42c256bbf880db3ac99sewardj   addr_to_seg_map_ENSURE_INIT();
434024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) {
435024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(keyW == ga);
436024598e40c84666cc311a42c256bbf880db3ac99sewardj      return (Seg*)valW;
437024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
438024598e40c84666cc311a42c256bbf880db3ac99sewardj      return NULL;
439024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
440024598e40c84666cc311a42c256bbf880db3ac99sewardj}
441024598e40c84666cc311a42c256bbf880db3ac99sewardj
442024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void bind_addr_to_Seg ( Addr ga, Seg* seg )
443024598e40c84666cc311a42c256bbf880db3ac99sewardj{
444024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool b;
445024598e40c84666cc311a42c256bbf880db3ac99sewardj   addr_to_seg_map_ENSURE_INIT();
446024598e40c84666cc311a42c256bbf880db3ac99sewardj   b = VG_(addToFM)( addr_to_seg_map, (UWord)ga, (UWord)seg );
447024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!b); /* else ga is already bound */
448024598e40c84666cc311a42c256bbf880db3ac99sewardj}
449024598e40c84666cc311a42c256bbf880db3ac99sewardj
450024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void unbind_addr_from_Seg ( Addr ga )
451024598e40c84666cc311a42c256bbf880db3ac99sewardj{
452024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool b;
453024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord keyW, valW;
454024598e40c84666cc311a42c256bbf880db3ac99sewardj   addr_to_seg_map_ENSURE_INIT();
455024598e40c84666cc311a42c256bbf880db3ac99sewardj   b = VG_(delFromFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga );
456024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(b); /* else ga was not already bound */
457024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(keyW == ga);
458024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(valW != 0);
459024598e40c84666cc311a42c256bbf880db3ac99sewardj}
460024598e40c84666cc311a42c256bbf880db3ac99sewardj
461024598e40c84666cc311a42c256bbf880db3ac99sewardj
462024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
463024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
464024598e40c84666cc311a42c256bbf880db3ac99sewardj//////////////////////////////////////////////////////////////
465024598e40c84666cc311a42c256bbf880db3ac99sewardj
466024598e40c84666cc311a42c256bbf880db3ac99sewardj// So that post_reg_write_clientcall knows the segment just allocated.
467024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* last_seg_added = NULL;
468024598e40c84666cc311a42c256bbf880db3ac99sewardj
469024598e40c84666cc311a42c256bbf880db3ac99sewardj// Returns the added heap segment
470024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size )
471024598e40c84666cc311a42c256bbf880db3ac99sewardj{
472024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg = get_Seg_for_malloc();
473024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */
474024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->addr = p;
475024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->szB  = size;
476024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->ec   = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
477024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!Seg__is_freed(seg));
478024598e40c84666cc311a42c256bbf880db3ac99sewardj
479024598e40c84666cc311a42c256bbf880db3ac99sewardj   bind_addr_to_Seg(p, seg);
480024598e40c84666cc311a42c256bbf880db3ac99sewardj
481024598e40c84666cc311a42c256bbf880db3ac99sewardj   last_seg_added = seg;
482024598e40c84666cc311a42c256bbf880db3ac99sewardj
483024598e40c84666cc311a42c256bbf880db3ac99sewardj   return seg;
484024598e40c84666cc311a42c256bbf880db3ac99sewardj}
485024598e40c84666cc311a42c256bbf880db3ac99sewardj
486024598e40c84666cc311a42c256bbf880db3ac99sewardj// Forward declarations
487024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void copy_mem( Addr from, Addr to, SizeT len );
488024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void set_mem_unknown ( Addr a, SizeT len );
489024598e40c84666cc311a42c256bbf880db3ac99sewardj
490024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline VG_REGPARM(1) Seg* nonptr_or_unknown(UWord x); /*fwds*/
491024598e40c84666cc311a42c256bbf880db3ac99sewardj
492024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
493024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* alloc_and_new_mem_heap ( ThreadId tid,
494024598e40c84666cc311a42c256bbf880db3ac99sewardj                               SizeT size, SizeT alignment, Bool is_zeroed )
495024598e40c84666cc311a42c256bbf880db3ac99sewardj{
496024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr p;
497024598e40c84666cc311a42c256bbf880db3ac99sewardj
498024598e40c84666cc311a42c256bbf880db3ac99sewardj   if ( ((SSizeT)size) < 0) return NULL;
499024598e40c84666cc311a42c256bbf880db3ac99sewardj
500024598e40c84666cc311a42c256bbf880db3ac99sewardj   p = (Addr)VG_(cli_malloc)(alignment, size);
501024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_zeroed) VG_(memset)((void*)p, 0, size);
502024598e40c84666cc311a42c256bbf880db3ac99sewardj
503024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( p, size );
504024598e40c84666cc311a42c256bbf880db3ac99sewardj   add_new_segment( tid, p, size );
505024598e40c84666cc311a42c256bbf880db3ac99sewardj
506024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__client_mallocs++;
507024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (void*)p;
508024598e40c84666cc311a42c256bbf880db3ac99sewardj}
509024598e40c84666cc311a42c256bbf880db3ac99sewardj
510024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void die_and_free_mem_heap ( ThreadId tid, Seg* seg )
511024598e40c84666cc311a42c256bbf880db3ac99sewardj{
512024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Empty and free the actual block
513024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!Seg__is_freed(seg));
514024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( seg->addr, seg->szB );
515024598e40c84666cc311a42c256bbf880db3ac99sewardj
516024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(cli_free)( (void*)seg->addr );
517024598e40c84666cc311a42c256bbf880db3ac99sewardj
518024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Remember where freed
519024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
520024598e40c84666cc311a42c256bbf880db3ac99sewardj
521024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_Seg_freed(seg);
522024598e40c84666cc311a42c256bbf880db3ac99sewardj   unbind_addr_from_Seg( seg->addr );
523024598e40c84666cc311a42c256bbf880db3ac99sewardj
524024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__client_frees++;
525024598e40c84666cc311a42c256bbf880db3ac99sewardj}
526024598e40c84666cc311a42c256bbf880db3ac99sewardj
527024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void handle_free_heap( ThreadId tid, void* p )
528024598e40c84666cc311a42c256bbf880db3ac99sewardj{
529024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg = find_Seg_by_addr( (Addr)p );
530024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!seg) {
531024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* freeing a block that wasn't malloc'd.  Ignore. */
532024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
533024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
534024598e40c84666cc311a42c256bbf880db3ac99sewardj   die_and_free_mem_heap( tid, seg );
535024598e40c84666cc311a42c256bbf880db3ac99sewardj}
536024598e40c84666cc311a42c256bbf880db3ac99sewardj
537024598e40c84666cc311a42c256bbf880db3ac99sewardj
538024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
539024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Shadow memory                                        ---*/
540024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
541024598e40c84666cc311a42c256bbf880db3ac99sewardj
542024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Shadow memory holds one Seg for each naturally aligned (guest)
543024598e40c84666cc311a42c256bbf880db3ac99sewardj   word.  For a 32 bit target (assuming host word size == guest word
544024598e40c84666cc311a42c256bbf880db3ac99sewardj   size) that means one Seg per 4 bytes, and each Seg occupies 4
545024598e40c84666cc311a42c256bbf880db3ac99sewardj   bytes.  For a 64 bit target that means one Seg per 8 bytes, and
546024598e40c84666cc311a42c256bbf880db3ac99sewardj   each Seg occupies 8 bytes.  Hence in each case the overall space
547024598e40c84666cc311a42c256bbf880db3ac99sewardj   overhead for shadow memory is 1:1.
548024598e40c84666cc311a42c256bbf880db3ac99sewardj
549024598e40c84666cc311a42c256bbf880db3ac99sewardj   This does however make it a bit tricky to size SecMap.vseg[], simce
550024598e40c84666cc311a42c256bbf880db3ac99sewardj   it needs to hold 16384 entries for 32 bit targets but only 8192
551024598e40c84666cc311a42c256bbf880db3ac99sewardj   entries for 64 bit targets. */
552024598e40c84666cc311a42c256bbf880db3ac99sewardj
553024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
554024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((unused))
555024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void pp_curr_ExeContext(void)
556024598e40c84666cc311a42c256bbf880db3ac99sewardj{
557024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(pp_ExeContext)(
558024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(get_ExeContext)(
559024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(get_current_or_recent_tid)() ) );
560024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(message)(Vg_UserMsg, "");
561024598e40c84666cc311a42c256bbf880db3ac99sewardj}
562024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
563024598e40c84666cc311a42c256bbf880db3ac99sewardj
564024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_x86) || defined(VGA_ppc32)
565024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_MASK         0xFFFC
566024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_SHIFT        2
567024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_4_ALIGNED(_a)
568024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SEC_MAP_WORDS             (0x10000UL / 4UL) /* 16k */
569024598e40c84666cc311a42c256bbf880db3ac99sewardj#elif defined(VGA_amd64) || defined(VGA_ppc64)
570024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_MASK         0xFFF8
571024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_SECMAP_SHIFT        3
572024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_8_ALIGNED(_a)
573024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define SEC_MAP_WORDS             (0x10000UL / 8UL) /* 8k */
574024598e40c84666cc311a42c256bbf880db3ac99sewardj#else
575024598e40c84666cc311a42c256bbf880db3ac99sewardj#  error "Unknown arch"
576024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
577024598e40c84666cc311a42c256bbf880db3ac99sewardj
578024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
579024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
580024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* vseg[SEC_MAP_WORDS];
581024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
582024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap;
583024598e40c84666cc311a42c256bbf880db3ac99sewardj
584024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SecMap  distinguished_secondary_map;
585024598e40c84666cc311a42c256bbf880db3ac99sewardj
586024598e40c84666cc311a42c256bbf880db3ac99sewardj/* An entry in the primary map.  base must be a 64k-aligned value, and
587024598e40c84666cc311a42c256bbf880db3ac99sewardj   sm points at the relevant secondary map.  The secondary may be
588024598e40c84666cc311a42c256bbf880db3ac99sewardj   either a real secondary, or the distinguished secondary.  DO NOT
589024598e40c84666cc311a42c256bbf880db3ac99sewardj   CHANGE THIS LAYOUT: the first word has to be the key for OSet fast
590024598e40c84666cc311a42c256bbf880db3ac99sewardj   lookups.
591024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
592024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
593024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
594024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr    base;
595024598e40c84666cc311a42c256bbf880db3ac99sewardj      SecMap* sm;
596024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
597024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt;
598024598e40c84666cc311a42c256bbf880db3ac99sewardj
599024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Primary map is an OSet of PriMapEnt (primap_L2), "fronted" by a
600024598e40c84666cc311a42c256bbf880db3ac99sewardj   cache (primap_L1). */
601024598e40c84666cc311a42c256bbf880db3ac99sewardj
602024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Tunable parameter: How big is the L1 queue? */
603024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_PRIMAP_L1 24
604024598e40c84666cc311a42c256bbf880db3ac99sewardj
605024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Tunable parameter: How far along the L1 queue to insert
606024598e40c84666cc311a42c256bbf880db3ac99sewardj   entries resulting from L2 lookups? */
607024598e40c84666cc311a42c256bbf880db3ac99sewardj#define PRIMAP_L1_INSERT_IX 12
608024598e40c84666cc311a42c256bbf880db3ac99sewardj
609024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic struct {
610024598e40c84666cc311a42c256bbf880db3ac99sewardj          Addr       base; // must be 64k aligned
611024598e40c84666cc311a42c256bbf880db3ac99sewardj          PriMapEnt* ent; // pointer to the matching primap_L2 node
612024598e40c84666cc311a42c256bbf880db3ac99sewardj       }
613024598e40c84666cc311a42c256bbf880db3ac99sewardj       primap_L1[N_PRIMAP_L1];
614024598e40c84666cc311a42c256bbf880db3ac99sewardj
615024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic OSet* primap_L2 = NULL;
616024598e40c84666cc311a42c256bbf880db3ac99sewardj
617024598e40c84666cc311a42c256bbf880db3ac99sewardj
618024598e40c84666cc311a42c256bbf880db3ac99sewardj/* # searches initiated in auxmap_L1, and # base cmps required */
619024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L1_searches  = 0;
620024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L1_cmps      = 0;
621024598e40c84666cc311a42c256bbf880db3ac99sewardj/* # of searches that missed in auxmap_L1 and therefore had to
622024598e40c84666cc311a42c256bbf880db3ac99sewardj   be handed to auxmap_L2. And the number of nodes inserted. */
623024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L2_searches  = 0;
624024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong n_primap_L2_nodes     = 0;
625024598e40c84666cc311a42c256bbf880db3ac99sewardj
626024598e40c84666cc311a42c256bbf880db3ac99sewardj
627024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_shadow_memory ( void )
628024598e40c84666cc311a42c256bbf880db3ac99sewardj{
629024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i;
630024598e40c84666cc311a42c256bbf880db3ac99sewardj
631024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < SEC_MAP_WORDS; i++)
632024598e40c84666cc311a42c256bbf880db3ac99sewardj      distinguished_secondary_map.vseg[i] = NONPTR;
633024598e40c84666cc311a42c256bbf880db3ac99sewardj
634024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < N_PRIMAP_L1; i++) {
635024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[i].base = 1; /* not 64k aligned, so doesn't match any
636024598e40c84666cc311a42c256bbf880db3ac99sewardj                                request ==> slot is empty */
637024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[i].ent  = NULL;
638024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
639024598e40c84666cc311a42c256bbf880db3ac99sewardj
640024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == offsetof(PriMapEnt,base));
641024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr) == sizeof(void*));
642024598e40c84666cc311a42c256bbf880db3ac99sewardj   primap_L2 = VG_(OSetGen_Create)( /*keyOff*/  offsetof(PriMapEnt,base),
643024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    /*fastCmp*/ NULL,
644024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(malloc), "pc.h_main.ism.1",
645024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(free) );
646024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(primap_L2);
647024598e40c84666cc311a42c256bbf880db3ac99sewardj}
648024598e40c84666cc311a42c256bbf880db3ac99sewardj
649024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void insert_into_primap_L1_at ( Word rank, PriMapEnt* ent )
650024598e40c84666cc311a42c256bbf880db3ac99sewardj{
651024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word i;
652024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(ent);
653024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(rank >= 0 && rank < N_PRIMAP_L1);
654024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = N_PRIMAP_L1-1; i > rank; i--)
655024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[i] = primap_L1[i-1];
656024598e40c84666cc311a42c256bbf880db3ac99sewardj   primap_L1[rank].base = ent->base;
657024598e40c84666cc311a42c256bbf880db3ac99sewardj   primap_L1[rank].ent  = ent;
658024598e40c84666cc311a42c256bbf880db3ac99sewardj}
659024598e40c84666cc311a42c256bbf880db3ac99sewardj
660024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline PriMapEnt* maybe_find_in_primap ( Addr a )
661024598e40c84666cc311a42c256bbf880db3ac99sewardj{
662024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt  key;
663024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt* res;
664024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word       i;
665024598e40c84666cc311a42c256bbf880db3ac99sewardj
666024598e40c84666cc311a42c256bbf880db3ac99sewardj   a &= ~(Addr)0xFFFF;
667024598e40c84666cc311a42c256bbf880db3ac99sewardj
668024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First search the front-cache, which is a self-organising
669024598e40c84666cc311a42c256bbf880db3ac99sewardj      list containing the most popular entries. */
670024598e40c84666cc311a42c256bbf880db3ac99sewardj
671024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (LIKELY(primap_L1[0].base == a))
672024598e40c84666cc311a42c256bbf880db3ac99sewardj      return primap_L1[0].ent;
673024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (LIKELY(primap_L1[1].base == a)) {
674024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr       t_base = primap_L1[0].base;
675024598e40c84666cc311a42c256bbf880db3ac99sewardj      PriMapEnt* t_ent  = primap_L1[0].ent;
676024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[0].base = primap_L1[1].base;
677024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[0].ent  = primap_L1[1].ent;
678024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[1].base = t_base;
679024598e40c84666cc311a42c256bbf880db3ac99sewardj      primap_L1[1].ent  = t_ent;
680024598e40c84666cc311a42c256bbf880db3ac99sewardj      return primap_L1[0].ent;
681024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
682024598e40c84666cc311a42c256bbf880db3ac99sewardj
683024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L1_searches++;
684024598e40c84666cc311a42c256bbf880db3ac99sewardj
685024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < N_PRIMAP_L1; i++) {
686024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (primap_L1[i].base == a) {
687024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
688024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
689024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
690024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0 && i <= N_PRIMAP_L1);
691024598e40c84666cc311a42c256bbf880db3ac99sewardj
692024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L1_cmps += (ULong)(i+1);
693024598e40c84666cc311a42c256bbf880db3ac99sewardj
694024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i < N_PRIMAP_L1) {
695024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (i > 0) {
696024598e40c84666cc311a42c256bbf880db3ac99sewardj         Addr       t_base = primap_L1[i-1].base;
697024598e40c84666cc311a42c256bbf880db3ac99sewardj         PriMapEnt* t_ent  = primap_L1[i-1].ent;
698024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-1].base = primap_L1[i-0].base;
699024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-1].ent  = primap_L1[i-0].ent;
700024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-0].base = t_base;
701024598e40c84666cc311a42c256bbf880db3ac99sewardj         primap_L1[i-0].ent  = t_ent;
702024598e40c84666cc311a42c256bbf880db3ac99sewardj         i--;
703024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
704024598e40c84666cc311a42c256bbf880db3ac99sewardj      return primap_L1[i].ent;
705024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
706024598e40c84666cc311a42c256bbf880db3ac99sewardj
707024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L2_searches++;
708024598e40c84666cc311a42c256bbf880db3ac99sewardj
709024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First see if we already have it. */
710024598e40c84666cc311a42c256bbf880db3ac99sewardj   key.base = a;
711024598e40c84666cc311a42c256bbf880db3ac99sewardj   key.sm   = 0;
712024598e40c84666cc311a42c256bbf880db3ac99sewardj
713024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = VG_(OSetGen_Lookup)(primap_L2, &key);
714024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (res)
715024598e40c84666cc311a42c256bbf880db3ac99sewardj      insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, res );
716024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
717024598e40c84666cc311a42c256bbf880db3ac99sewardj}
718024598e40c84666cc311a42c256bbf880db3ac99sewardj
719024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic SecMap* alloc_secondary_map ( void )
720024598e40c84666cc311a42c256bbf880db3ac99sewardj{
721024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap* map;
722024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt  i;
723024598e40c84666cc311a42c256bbf880db3ac99sewardj
724024598e40c84666cc311a42c256bbf880db3ac99sewardj   // JRS 2008-June-25: what's the following assertion for?
725024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (sizeof(SecMap) % VKI_MAX_PAGE_SIZE));
726024598e40c84666cc311a42c256bbf880db3ac99sewardj
727024598e40c84666cc311a42c256bbf880db3ac99sewardj   map = VG_(am_shadow_alloc)( sizeof(SecMap) );
728024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (map == NULL)
729024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(out_of_memory_NORETURN)( "annelid:allocate new SecMap",
730024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   sizeof(SecMap) );
731024598e40c84666cc311a42c256bbf880db3ac99sewardj
732024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < SEC_MAP_WORDS; i++)
733024598e40c84666cc311a42c256bbf880db3ac99sewardj      map->vseg[i] = NONPTR;
734024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("XXX new secmap %p\n", map);
735024598e40c84666cc311a42c256bbf880db3ac99sewardj   return map;
736024598e40c84666cc311a42c256bbf880db3ac99sewardj}
737024598e40c84666cc311a42c256bbf880db3ac99sewardj
738024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic PriMapEnt* find_or_alloc_in_primap ( Addr a )
739024598e40c84666cc311a42c256bbf880db3ac99sewardj{
740024598e40c84666cc311a42c256bbf880db3ac99sewardj   PriMapEnt *nyu, *res;
741024598e40c84666cc311a42c256bbf880db3ac99sewardj
742024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First see if we already have it. */
743024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = maybe_find_in_primap( a );
744024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (LIKELY(res))
745024598e40c84666cc311a42c256bbf880db3ac99sewardj      return res;
746024598e40c84666cc311a42c256bbf880db3ac99sewardj
747024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Ok, there's no entry in the secondary map, so we'll have
748024598e40c84666cc311a42c256bbf880db3ac99sewardj      to allocate one. */
749024598e40c84666cc311a42c256bbf880db3ac99sewardj   a &= ~(Addr)0xFFFF;
750024598e40c84666cc311a42c256bbf880db3ac99sewardj
751024598e40c84666cc311a42c256bbf880db3ac99sewardj   nyu = (PriMapEnt*) VG_(OSetGen_AllocNode)(
752024598e40c84666cc311a42c256bbf880db3ac99sewardj                         primap_L2, sizeof(PriMapEnt) );
753024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(nyu);
754024598e40c84666cc311a42c256bbf880db3ac99sewardj   nyu->base = a;
755024598e40c84666cc311a42c256bbf880db3ac99sewardj   nyu->sm   = alloc_secondary_map();
756024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(nyu->sm);
757024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(OSetGen_Insert)( primap_L2, nyu );
758024598e40c84666cc311a42c256bbf880db3ac99sewardj   insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, nyu );
759024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_primap_L2_nodes++;
760024598e40c84666cc311a42c256bbf880db3ac99sewardj   return nyu;
761024598e40c84666cc311a42c256bbf880db3ac99sewardj}
762024598e40c84666cc311a42c256bbf880db3ac99sewardj
763024598e40c84666cc311a42c256bbf880db3ac99sewardj/////////////////////////////////////////////////
764024598e40c84666cc311a42c256bbf880db3ac99sewardj
765024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: 'a' must be naturally word aligned for the host.
766024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Seg* get_mem_vseg ( Addr a )
767024598e40c84666cc311a42c256bbf880db3ac99sewardj{
768024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap* sm     = find_or_alloc_in_primap(a)->sm;
769024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord   sm_off = (a & SHMEM_SECMAP_MASK) >> SHMEM_SECMAP_SHIFT;
770024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(SHMEM_IS_WORD_ALIGNED(a));
771024598e40c84666cc311a42c256bbf880db3ac99sewardj   return sm->vseg[sm_off];
772024598e40c84666cc311a42c256bbf880db3ac99sewardj}
773024598e40c84666cc311a42c256bbf880db3ac99sewardj
774024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: 'a' must be naturally word aligned for the host.
775024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline void set_mem_vseg ( Addr a, Seg* vseg )
776024598e40c84666cc311a42c256bbf880db3ac99sewardj{
777024598e40c84666cc311a42c256bbf880db3ac99sewardj   SecMap* sm     = find_or_alloc_in_primap(a)->sm;
778024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord   sm_off = (a & SHMEM_SECMAP_MASK) >> SHMEM_SECMAP_SHIFT;
779024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(SHMEM_IS_WORD_ALIGNED(a));
780024598e40c84666cc311a42c256bbf880db3ac99sewardj   sm->vseg[sm_off] = vseg;
781024598e40c84666cc311a42c256bbf880db3ac99sewardj}
782024598e40c84666cc311a42c256bbf880db3ac99sewardj
783024598e40c84666cc311a42c256bbf880db3ac99sewardj// Returns UNKNOWN if no matches.  Never returns BOTTOM or NONPTR.
784024598e40c84666cc311a42c256bbf880db3ac99sewardj// Also, only returns in-use segments, not freed ones.
785024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* get_Seg_containing_addr_SLOW( Addr a )
786024598e40c84666cc311a42c256bbf880db3ac99sewardj{
787024598e40c84666cc311a42c256bbf880db3ac99sewardj   SegGroup* group;
788024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord i;
789024598e40c84666cc311a42c256bbf880db3ac99sewardj   stats__slow_searches++;
790024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (group = group_list; group; group = group->admin) {
791024598e40c84666cc311a42c256bbf880db3ac99sewardj      for (i = 0; i < group->nextfree; i++) {
792024598e40c84666cc311a42c256bbf880db3ac99sewardj         stats__slow_totcmps++;
793024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (Seg__is_freed(&group->segs[i]))
794024598e40c84666cc311a42c256bbf880db3ac99sewardj            continue;
795024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (group->segs[i].addr <= a
796024598e40c84666cc311a42c256bbf880db3ac99sewardj             && a < group->segs[i].addr + group->segs[i].szB)
797024598e40c84666cc311a42c256bbf880db3ac99sewardj            return &group->segs[i];
798024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
799024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
800024598e40c84666cc311a42c256bbf880db3ac99sewardj   return UNKNOWN;
801024598e40c84666cc311a42c256bbf880db3ac99sewardj}
802024598e40c84666cc311a42c256bbf880db3ac99sewardj
803024598e40c84666cc311a42c256bbf880db3ac99sewardj
804024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
805024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- malloc() et al replacements                          ---*/
806024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
807024598e40c84666cc311a42c256bbf880db3ac99sewardj
808024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_malloc ( ThreadId tid, SizeT n )
809024598e40c84666cc311a42c256bbf880db3ac99sewardj{
810024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
811024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        /*is_zeroed*/False );
812024598e40c84666cc311a42c256bbf880db3ac99sewardj}
813024598e40c84666cc311a42c256bbf880db3ac99sewardj
814024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace___builtin_new ( ThreadId tid, SizeT n )
815024598e40c84666cc311a42c256bbf880db3ac99sewardj{
816024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
817024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           /*is_zeroed*/False );
818024598e40c84666cc311a42c256bbf880db3ac99sewardj}
819024598e40c84666cc311a42c256bbf880db3ac99sewardj
820024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
821024598e40c84666cc311a42c256bbf880db3ac99sewardj{
822024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
823024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           /*is_zeroed*/False );
824024598e40c84666cc311a42c256bbf880db3ac99sewardj}
825024598e40c84666cc311a42c256bbf880db3ac99sewardj
826024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
827024598e40c84666cc311a42c256bbf880db3ac99sewardj{
828024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, n, align,
829024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        /*is_zeroed*/False );
830024598e40c84666cc311a42c256bbf880db3ac99sewardj}
831024598e40c84666cc311a42c256bbf880db3ac99sewardj
832024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
833024598e40c84666cc311a42c256bbf880db3ac99sewardj{
834024598e40c84666cc311a42c256bbf880db3ac99sewardj   return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
835024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        /*is_zeroed*/True );
836024598e40c84666cc311a42c256bbf880db3ac99sewardj}
837024598e40c84666cc311a42c256bbf880db3ac99sewardj
838024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_replace_free ( ThreadId tid, void* p )
839024598e40c84666cc311a42c256bbf880db3ac99sewardj{
840024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Should arguably check here if p.vseg matches the segID of the
841024598e40c84666cc311a42c256bbf880db3ac99sewardj   // pointed-to block... unfortunately, by this stage, we don't know what
842024598e40c84666cc311a42c256bbf880db3ac99sewardj   // p.vseg is, because we don't know the address of p (the p here is a
843024598e40c84666cc311a42c256bbf880db3ac99sewardj   // copy, and we've lost the address of its source).  To do so would
844024598e40c84666cc311a42c256bbf880db3ac99sewardj   // require passing &p in, which would require rewriting part of
845024598e40c84666cc311a42c256bbf880db3ac99sewardj   // vg_replace_malloc.c... argh.
846024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
847024598e40c84666cc311a42c256bbf880db3ac99sewardj   // However, Memcheck does free checking, and will catch almost all
848024598e40c84666cc311a42c256bbf880db3ac99sewardj   // violations this checking would have caught.  (Would only miss if we
849024598e40c84666cc311a42c256bbf880db3ac99sewardj   // unluckily passed an unrelated pointer to the very start of a heap
850024598e40c84666cc311a42c256bbf880db3ac99sewardj   // block that was unrelated to that block.  This is very unlikely!)    So
851024598e40c84666cc311a42c256bbf880db3ac99sewardj   // we haven't lost much.
852024598e40c84666cc311a42c256bbf880db3ac99sewardj
853024598e40c84666cc311a42c256bbf880db3ac99sewardj   handle_free_heap(tid, p);
854024598e40c84666cc311a42c256bbf880db3ac99sewardj}
855024598e40c84666cc311a42c256bbf880db3ac99sewardj
856024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_replace___builtin_delete ( ThreadId tid, void* p )
857024598e40c84666cc311a42c256bbf880db3ac99sewardj{
858024598e40c84666cc311a42c256bbf880db3ac99sewardj   handle_free_heap(tid, p);
859024598e40c84666cc311a42c256bbf880db3ac99sewardj}
860024598e40c84666cc311a42c256bbf880db3ac99sewardj
861024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_replace___builtin_vec_delete ( ThreadId tid, void* p )
862024598e40c84666cc311a42c256bbf880db3ac99sewardj{
863024598e40c84666cc311a42c256bbf880db3ac99sewardj   handle_free_heap(tid, p);
864024598e40c84666cc311a42c256bbf880db3ac99sewardj}
865024598e40c84666cc311a42c256bbf880db3ac99sewardj
866024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
867024598e40c84666cc311a42c256bbf880db3ac99sewardj{
868024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* seg;
869024598e40c84666cc311a42c256bbf880db3ac99sewardj
870024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* First try and find the block. */
871024598e40c84666cc311a42c256bbf880db3ac99sewardj   seg = find_Seg_by_addr( (Addr)p_old );
872024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!seg)
873024598e40c84666cc311a42c256bbf880db3ac99sewardj      return NULL;
874024598e40c84666cc311a42c256bbf880db3ac99sewardj
875024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(seg->addr == (Addr)p_old);
876024598e40c84666cc311a42c256bbf880db3ac99sewardj
877024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (new_size <= seg->szB) {
878024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* new size is smaller: allocate, copy from old to new */
879024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
880024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(memcpy)((void*)p_new, p_old, new_size);
881024598e40c84666cc311a42c256bbf880db3ac99sewardj
882024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Notification: copy retained part */
883024598e40c84666cc311a42c256bbf880db3ac99sewardj      copy_mem       ( (Addr)p_old, p_new, new_size );
884024598e40c84666cc311a42c256bbf880db3ac99sewardj
885024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Free old memory */
886024598e40c84666cc311a42c256bbf880db3ac99sewardj      die_and_free_mem_heap( tid, seg );
887024598e40c84666cc311a42c256bbf880db3ac99sewardj
888024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This has to be after die_and_free_mem_heap, otherwise the
889024598e40c84666cc311a42c256bbf880db3ac99sewardj         former succeeds in shorting out the new block, not the
890024598e40c84666cc311a42c256bbf880db3ac99sewardj         old, in the case when both are on the same list.  */
891024598e40c84666cc311a42c256bbf880db3ac99sewardj      add_new_segment ( tid, p_new, new_size );
892024598e40c84666cc311a42c256bbf880db3ac99sewardj
893024598e40c84666cc311a42c256bbf880db3ac99sewardj      return (void*)p_new;
894024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
895024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* new size is bigger: allocate, copy from old to new */
896024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
897024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(memcpy)((void*)p_new, p_old, seg->szB);
898024598e40c84666cc311a42c256bbf880db3ac99sewardj
899024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Notification: first half kept and copied, second half new */
900024598e40c84666cc311a42c256bbf880db3ac99sewardj      copy_mem       ( (Addr)p_old, p_new, seg->szB );
901024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_unknown( p_new + seg->szB, new_size - seg->szB );
902024598e40c84666cc311a42c256bbf880db3ac99sewardj
903024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Free old memory */
904024598e40c84666cc311a42c256bbf880db3ac99sewardj      die_and_free_mem_heap( tid, seg );
905024598e40c84666cc311a42c256bbf880db3ac99sewardj
906024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This has to be after die_and_free_mem_heap, otherwise the
907024598e40c84666cc311a42c256bbf880db3ac99sewardj         former succeeds in shorting out the new block, not the old,
908024598e40c84666cc311a42c256bbf880db3ac99sewardj         in the case when both are on the same list.  NB jrs
909024598e40c84666cc311a42c256bbf880db3ac99sewardj         2008-Sept-11: not sure if this comment is valid/correct any
910024598e40c84666cc311a42c256bbf880db3ac99sewardj         more -- I suspect not. */
911024598e40c84666cc311a42c256bbf880db3ac99sewardj      add_new_segment ( tid, p_new, new_size );
912024598e40c84666cc311a42c256bbf880db3ac99sewardj
913024598e40c84666cc311a42c256bbf880db3ac99sewardj      return (void*)p_new;
914024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
915024598e40c84666cc311a42c256bbf880db3ac99sewardj}
916024598e40c84666cc311a42c256bbf880db3ac99sewardj
917024598e40c84666cc311a42c256bbf880db3ac99sewardj
918024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
919024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Memory events                                        ---*/
920024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
921024598e40c84666cc311a42c256bbf880db3ac99sewardj
922024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
923024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid set_mem ( Addr a, SizeT len, Seg* seg )
924024598e40c84666cc311a42c256bbf880db3ac99sewardj{
925024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr end;
926024598e40c84666cc311a42c256bbf880db3ac99sewardj
927024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == len)
928024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
929024598e40c84666cc311a42c256bbf880db3ac99sewardj
930024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (len > 100 * 1000 * 1000)
931024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg,
932024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "Warning: set address range state: large range %lu", len);
933024598e40c84666cc311a42c256bbf880db3ac99sewardj
934024598e40c84666cc311a42c256bbf880db3ac99sewardj   a   = VG_ROUNDDN(a,       sizeof(UWord));
935024598e40c84666cc311a42c256bbf880db3ac99sewardj   end = VG_ROUNDUP(a + len, sizeof(UWord));
936024598e40c84666cc311a42c256bbf880db3ac99sewardj   for ( ; a < end; a += sizeof(UWord))
937024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg(a, seg);
938024598e40c84666cc311a42c256bbf880db3ac99sewardj}
939024598e40c84666cc311a42c256bbf880db3ac99sewardj
940024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void set_mem_unknown( Addr a, SizeT len )
941024598e40c84666cc311a42c256bbf880db3ac99sewardj{
942024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem( a, len, UNKNOWN );
943024598e40c84666cc311a42c256bbf880db3ac99sewardj}
944024598e40c84666cc311a42c256bbf880db3ac99sewardj
945024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void set_mem_nonptr( Addr a, UInt len )
946024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
947024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem( a, len, NONPTR );
948024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
949024598e40c84666cc311a42c256bbf880db3ac99sewardj
950024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_new_mem_startup( Addr a, SizeT len,
951024598e40c84666cc311a42c256bbf880db3ac99sewardj                        Bool rr, Bool ww, Bool xx, ULong di_handle )
952024598e40c84666cc311a42c256bbf880db3ac99sewardj{
953024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("new_mem_startup(%#lx,%lu)\n", a, len);
954024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( a, len );
955024598e40c84666cc311a42c256bbf880db3ac99sewardj   //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
956024598e40c84666cc311a42c256bbf880db3ac99sewardj}
957024598e40c84666cc311a42c256bbf880db3ac99sewardj
958024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // XXX: Currently not doing anything with brk() -- new segments, or not?
959024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Proper way to do it would be to grow/shrink a single, special brk segment.
960024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
961024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // brk is difficult: it defines a single segment, of changeable size.
962024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // It starts off with size zero, at the address given by brk(0).  There are
963024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // no pointers within the program to it.  Any subsequent calls by the
964024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // program to brk() (possibly growing or shrinking it) return pointers to
965024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // the *end* of the segment (nb: this is the kernel brk(), which is
966024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // different to the libc brk()).
967024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
968024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // If fixing this, don't forget to update the brk case in SK_(post_syscall).
969024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
970024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Nb: not sure if the return value is the last byte addressible, or one
971024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // past the end of the segment.
972024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //
973024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void new_mem_brk( Addr a, UInt len )
974024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
975024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
976024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    //VG_(skin_panic)("can't handle new_mem_brk");
977024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
978024598e40c84666cc311a42c256bbf880db3ac99sewardj
979024598e40c84666cc311a42c256bbf880db3ac99sewardj// Not quite right:  if you mmap a segment into a specified place, it could
980024598e40c84666cc311a42c256bbf880db3ac99sewardj// be legitimate to do certain arithmetic with the pointer that it wouldn't
981024598e40c84666cc311a42c256bbf880db3ac99sewardj// otherwise.  Hopefully this is rare, though.
982024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_new_mem_mmap( Addr a, SizeT len,
983024598e40c84666cc311a42c256bbf880db3ac99sewardj                     Bool rr, Bool ww, Bool xx, ULong di_handle )
984024598e40c84666cc311a42c256bbf880db3ac99sewardj{
985024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("new_mem_mmap(%#lx,%lu)\n", a, len);
986024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #if 0
987024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    Seg seg = NULL;
988024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
989024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // Check for overlapping segments
990024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #if 0
991024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___a   = a;    // 'free' variable
992024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___len = len;  // 'free' variable
993024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    seg = (Seg)VG_(HT_first_match) ( mlist, is_overlapping_seg );
994024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___a   = 0;    // paranoia, reset
995024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    is_overlapping_seg___len = 0;    // paranoia, reset
996024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #endif
997024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
998024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // XXX: do this check properly with ISLists
999024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1000024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if ( ISList__findI( seglist, a, &seg )) {
1001024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       sk_assert(SegMmap == seg->status || SegMmapFree == seg->status);
1002024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (SegMmap == seg->status)
1003024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1004024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    }
1005024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1006024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (NULL != seg) {
1007024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       // Right, we found an overlap
1008024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (VG_(clo_verbosity) > 1)
1009024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          VG_(message)(Vg_UserMsg, "mmap overlap:  old: %#lx, %d;  new: %#lx, %d",
1010024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz                                   seg->left, Seg__size(seg), a, len);
1011024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (seg->left <= a && a <= seg->right) {
1012024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // New one truncates end of the old one.  Nb: we don't adjust its
1013024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // size, because the first segment's pointer can be (and for
1014024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // Konqueror, is) legitimately used to access parts of the second
1015024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // segment.  At least, I assume Konqueror is doing something legal.
1016024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          // so that a size mismatch upon munmap isn't a problem.
1017024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //         seg->size = a - seg->data;
1018024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //         seg->is_truncated_map = True;
1019024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //         if (VG_(clo_verbosity) > 1)
1020024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //            VG_(message)(Vg_UserMsg, "old seg truncated to length %d",
1021024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //                                     seg->size);
1022024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       } else {
1023024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          VG_(skin_panic)("Can't handle this mmap() overlap case");
1024024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       }
1025024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    }
1026024598e40c84666cc311a42c256bbf880db3ac99sewardj   set_mem_unknown( a, len );
1027024598e40c84666cc311a42c256bbf880db3ac99sewardj   //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1028024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz #endif
1029024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1030024598e40c84666cc311a42c256bbf880db3ac99sewardj
1031024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void copy_mem( Addr from, Addr to, SizeT len )
1032024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1033024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr fromend = from + len;
1034024598e40c84666cc311a42c256bbf880db3ac99sewardj
1035024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Must be aligned due to malloc always returning aligned objects.
1036024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(VG_IS_8_ALIGNED(from) && VG_IS_8_ALIGNED(to));
1037024598e40c84666cc311a42c256bbf880db3ac99sewardj
1038024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Must only be called with positive len.
1039024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == len)
1040024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
1041024598e40c84666cc311a42c256bbf880db3ac99sewardj
1042024598e40c84666cc311a42c256bbf880db3ac99sewardj   for ( ; from < fromend; from += sizeof(UWord), to += sizeof(UWord))
1043024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( to, get_mem_vseg(from) );
1044024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1045024598e40c84666cc311a42c256bbf880db3ac99sewardj
1046024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Similar to SK_(realloc)()
1047024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void copy_mem_remap( Addr from, Addr to, UInt len )
1048024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1049024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    VG_(skin_panic)("argh: copy_mem_remap");
1050024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1051024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1052024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void die_mem_brk( Addr a, UInt len )
1053024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1054024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
1055024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz //   VG_(skin_panic)("can't handle die_mem_brk()");
1056024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1057024598e40c84666cc311a42c256bbf880db3ac99sewardj
1058024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_die_mem_munmap( Addr a, SizeT len )
1059024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1060024598e40c84666cc311a42c256bbf880db3ac99sewardj//   handle_free_munmap( (void*)a, len );
1061024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1062024598e40c84666cc311a42c256bbf880db3ac99sewardj
1063024598e40c84666cc311a42c256bbf880db3ac99sewardj// Don't need to check all addresses within the block; in the absence of
1064024598e40c84666cc311a42c256bbf880db3ac99sewardj// discontiguous segments, the segments for the first and last bytes should
1065024598e40c84666cc311a42c256bbf880db3ac99sewardj// be the same.  Can't easily check the pointer segment matches the block
1066024598e40c84666cc311a42c256bbf880db3ac99sewardj// segment, unfortunately, but the first/last check should catch most
1067024598e40c84666cc311a42c256bbf880db3ac99sewardj// errors.
1068024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void pre_mem_access2 ( CorePart part, ThreadId tid, Char* str,
1069024598e40c84666cc311a42c256bbf880db3ac99sewardj                              Addr s/*tart*/, Addr e/*nd*/ )
1070024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1071024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg  *seglo, *seghi;
1072024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool s_in_seglo, s_in_seghi, e_in_seglo, e_in_seghi;
1073024598e40c84666cc311a42c256bbf880db3ac99sewardj
1074024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Don't check code being translated -- very slow, and not much point
1075024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (Vg_CoreTranslate == part) return;
1076024598e40c84666cc311a42c256bbf880db3ac99sewardj
1077024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Don't check the signal case -- only happens in core, no need to check
1078024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (Vg_CoreSignal == part) return;
1079024598e40c84666cc311a42c256bbf880db3ac99sewardj
1080024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Only expect syscalls after this point
1081024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (part != Vg_CoreSysCall) {
1082024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("part = %d\n", part);
1083024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("unknown corepart in pre_mem_access2");
1084024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1085024598e40c84666cc311a42c256bbf880db3ac99sewardj
1086024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Check first and last bytes match
1087024598e40c84666cc311a42c256bbf880db3ac99sewardj   seglo = get_Seg_containing_addr_SLOW( s );
1088024598e40c84666cc311a42c256bbf880db3ac99sewardj   seghi = get_Seg_containing_addr_SLOW( e );
1089024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert( BOTTOM != seglo && NONPTR != seglo );
1090024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert( BOTTOM != seghi && NONPTR != seghi );
1091024598e40c84666cc311a42c256bbf880db3ac99sewardj
1092024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* so seglo and seghi are either UNKNOWN or P(..) */
1093024598e40c84666cc311a42c256bbf880db3ac99sewardj   s_in_seglo
1094024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seglo)
1095024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seglo->addr <= s && s < seglo->addr + seglo->szB;
1096024598e40c84666cc311a42c256bbf880db3ac99sewardj   s_in_seghi
1097024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seghi)
1098024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seghi->addr <= s && s < seghi->addr + seghi->szB;
1099024598e40c84666cc311a42c256bbf880db3ac99sewardj   e_in_seglo
1100024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seglo)
1101024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seglo->addr <= e && e < seglo->addr + seglo->szB;
1102024598e40c84666cc311a42c256bbf880db3ac99sewardj   e_in_seghi
1103024598e40c84666cc311a42c256bbf880db3ac99sewardj      = is_known_segment(seghi)
1104024598e40c84666cc311a42c256bbf880db3ac99sewardj        && seghi->addr <= e && e < seghi->addr + seghi->szB;
1105024598e40c84666cc311a42c256bbf880db3ac99sewardj
1106024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if start and end are in different, but known
1107024598e40c84666cc311a42c256bbf880db3ac99sewardj      segments */
1108024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seglo) && is_known_segment(seghi)
1109024598e40c84666cc311a42c256bbf880db3ac99sewardj       && seglo != seghi) {
1110024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
1111024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1112024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
1113024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if start is in a known segment but end isn't */
1114024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seglo) && !is_known_segment(seghi)) {
1115024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
1116024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1117024598e40c84666cc311a42c256bbf880db3ac99sewardj   else
1118024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* record an error if end is in a known segment but start isn't */
1119024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!is_known_segment(seglo) && is_known_segment(seghi)) {
1120024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi);
1121024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1122024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1123024598e40c84666cc311a42c256bbf880db3ac99sewardj
1124024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
1125024598e40c84666cc311a42c256bbf880db3ac99sewardj                        Addr base, SizeT size )
1126024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1127024598e40c84666cc311a42c256bbf880db3ac99sewardj   pre_mem_access2( part, tid, s, base, base + size - 1 );
1128024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1129024598e40c84666cc311a42c256bbf880db3ac99sewardj
1130024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
1131024598e40c84666cc311a42c256bbf880db3ac99sewardj                             Char* s, Addr lo )
1132024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1133024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr hi = lo;
1134024598e40c84666cc311a42c256bbf880db3ac99sewardj
1135024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Nb: the '\0' must be included in the lo...hi range
1136024598e40c84666cc311a42c256bbf880db3ac99sewardj   while ('\0' != *(Char*)hi) hi++;
1137024598e40c84666cc311a42c256bbf880db3ac99sewardj   pre_mem_access2( part, tid, s, lo, hi );
1138024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1139024598e40c84666cc311a42c256bbf880db3ac99sewardj
1140024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_mem_write(Addr a, UInt len)
1141024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1142024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    set_mem_unknown(a, len);
1143024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1144024598e40c84666cc311a42c256bbf880db3ac99sewardj
1145024598e40c84666cc311a42c256bbf880db3ac99sewardj
1146024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1147024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Register event handlers                              ---*/
1148024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
1149024598e40c84666cc311a42c256bbf880db3ac99sewardj
1150024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_regs_write_init ( void )
1151024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
1152024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    UInt i;
1153024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    for (i = R_EAX; i <= R_EDI; i++)
1154024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       VG_(set_shadow_archreg)( i, (UInt)UNKNOWN );
1155024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1156024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    // Don't bother about eflags
1157024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
1158024598e40c84666cc311a42c256bbf880db3ac99sewardj
1159024598e40c84666cc311a42c256bbf880db3ac99sewardj// BEGIN move this uglyness to pc_machine.c
1160024598e40c84666cc311a42c256bbf880db3ac99sewardj
1161024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_big_endian ( void ) {
1162024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt x = 0x11223344;
1163024598e40c84666cc311a42c256bbf880db3ac99sewardj   return 0x1122 == *(UShort*)(&x);
1164024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1165024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_little_endian ( void ) {
1166024598e40c84666cc311a42c256bbf880db3ac99sewardj   UInt x = 0x11223344;
1167024598e40c84666cc311a42c256bbf880db3ac99sewardj   return 0x3344 == *(UShort*)(&x);
1168024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1169024598e40c84666cc311a42c256bbf880db3ac99sewardj
1170024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_INTREGINFO_OFFSETS 4
1171024598e40c84666cc311a42c256bbf880db3ac99sewardj
1172024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Holds the result of a query to 'get_IntRegInfo'.  Valid values for
1173024598e40c84666cc311a42c256bbf880db3ac99sewardj   n_offsets are:
1174024598e40c84666cc311a42c256bbf880db3ac99sewardj
1175024598e40c84666cc311a42c256bbf880db3ac99sewardj   -1: means the queried guest state slice exactly matches
1176024598e40c84666cc311a42c256bbf880db3ac99sewardj       one integer register
1177024598e40c84666cc311a42c256bbf880db3ac99sewardj
1178024598e40c84666cc311a42c256bbf880db3ac99sewardj   0: means the queried guest state slice does not overlap any
1179024598e40c84666cc311a42c256bbf880db3ac99sewardj      integer registers
1180024598e40c84666cc311a42c256bbf880db3ac99sewardj
1181024598e40c84666cc311a42c256bbf880db3ac99sewardj   1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset
1182024598e40c84666cc311a42c256bbf880db3ac99sewardj      overlaps n_offsets different integer registers, and their base
1183024598e40c84666cc311a42c256bbf880db3ac99sewardj      offsets are placed in the offsets array.
1184024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
1185024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
1186024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
1187024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int offsets[N_INTREGINFO_OFFSETS];
1188024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int n_offsets;
1189024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1190024598e40c84666cc311a42c256bbf880db3ac99sewardj   IntRegInfo;
1191024598e40c84666cc311a42c256bbf880db3ac99sewardj
1192024598e40c84666cc311a42c256bbf880db3ac99sewardj
1193024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_x86)
1194024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_x86.h"
1195024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State)
1196024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1197024598e40c84666cc311a42c256bbf880db3ac99sewardj
1198024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_amd64)
1199024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_amd64.h"
1200024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State)
1201024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO)
1202024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO)
1203024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1204024598e40c84666cc311a42c256bbf880db3ac99sewardj
1205024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc32)
1206024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc32.h"
1207024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State)
1208024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1209024598e40c84666cc311a42c256bbf880db3ac99sewardj
1210024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc64)
1211024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc64.h"
1212024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
1213024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
1214024598e40c84666cc311a42c256bbf880db3ac99sewardj
1215024598e40c84666cc311a42c256bbf880db3ac99sewardj
1216024598e40c84666cc311a42c256bbf880db3ac99sewardj/* See description on definition of type IntRegInfo. */
1217024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
1218024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1219024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------------- x86 --------------------- */
1220024598e40c84666cc311a42c256bbf880db3ac99sewardj
1221024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86)
1222024598e40c84666cc311a42c256bbf880db3ac99sewardj
1223024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1224024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestX86State,guest_##_fieldname))
1225024598e40c84666cc311a42c256bbf880db3ac99sewardj
1226024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1227024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1228024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1229024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is21 = sz == 2 || sz == 1;
1230024598e40c84666cc311a42c256bbf880db3ac99sewardj
1231024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1232024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_little_endian());
1233024598e40c84666cc311a42c256bbf880db3ac99sewardj
1234024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1235024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1236024598e40c84666cc311a42c256bbf880db3ac99sewardj
1237024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1238024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)     && is4) goto exactly1;
1239024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)     && is4) goto exactly1;
1240024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)     && is4) goto exactly1;
1241024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBX)     && is4) goto exactly1;
1242024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESP)     && is4) goto exactly1;
1243024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBP)     && is4) goto exactly1;
1244024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESI)     && is4) goto exactly1;
1245024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDI)     && is4) goto exactly1;
1246024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EIP)     && is4) goto none;
1247024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_OP)   && is4) goto none;
1248024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP1) && is4) goto none;
1249024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP2) && is4) goto none;
1250024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_NDEP) && is4) goto none;
1251024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(DFLAG)   && is4) goto none;
1252024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(IDFLAG)  && is4) goto none;
1253024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ACFLAG)  && is4) goto none;
1254024598e40c84666cc311a42c256bbf880db3ac99sewardj
1255024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Partial accesses to integer registers */
1256024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)     && is21) {         o -= 0; goto contains_o; }
1257024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EAX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1258024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)     && is21) {         o -= 0; goto contains_o; }
1259024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ECX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1260024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EBX)     && is21) {         o -= 0; goto contains_o; }
1261024598e40c84666cc311a42c256bbf880db3ac99sewardj   // bl case
1262024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)     && is21) {         o -= 0; goto contains_o; }
1263024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDX)+1   && is21) { o -= 1; o -= 0; goto contains_o; }
1264024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(ESI)     && is21) {         o -= 0; goto contains_o; }
1265024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EDI)     && is21) {         o -= 0; goto contains_o; }
1266024598e40c84666cc311a42c256bbf880db3ac99sewardj
1267024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Segment related guff */
1268024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GS)  && sz == 2) goto none;
1269024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LDT) && is4) goto none;
1270024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GDT) && is4) goto none;
1271024598e40c84666cc311a42c256bbf880db3ac99sewardj
1272024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1273024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(SSEROUND) && is4) goto none;
1274024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND)  && is4) goto none;
1275024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)   && is4) goto none;
1276024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FTOP)     && is4) goto none;
1277024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPTAG)    && sz == 8) goto none;
1278024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FC3210)   && is4) goto none;
1279024598e40c84666cc311a42c256bbf880db3ac99sewardj
1280024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* xmm registers, including arbitrary sub-parts */
1281024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1282024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1283024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1284024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1285024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1286024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1287024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1288024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1289024598e40c84666cc311a42c256bbf880db3ac99sewardj
1290024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1291024598e40c84666cc311a42c256bbf880db3ac99sewardj      to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1292024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1293024598e40c84666cc311a42c256bbf880db3ac99sewardj
1294024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* the entire mmx/x87 register bank in one big piece */
1295024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPREG) && sz == 64) goto none;
1296024598e40c84666cc311a42c256bbf880db3ac99sewardj
1297024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz);
1298024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1299024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1300024598e40c84666cc311a42c256bbf880db3ac99sewardj
1301024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- amd64 -------------------- */
1302024598e40c84666cc311a42c256bbf880db3ac99sewardj
1303024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64)
1304024598e40c84666cc311a42c256bbf880db3ac99sewardj
1305024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1306024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestAMD64State,guest_##_fieldname))
1307024598e40c84666cc311a42c256bbf880db3ac99sewardj
1308024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o     = offset;
1309024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz    = szB;
1310024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is421 = sz == 4 || sz == 2 || sz == 1;
1311024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8   = sz == 8;
1312024598e40c84666cc311a42c256bbf880db3ac99sewardj
1313024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1314024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_little_endian());
1315024598e40c84666cc311a42c256bbf880db3ac99sewardj
1316024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1317024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1318024598e40c84666cc311a42c256bbf880db3ac99sewardj
1319024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1320024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)     && is8) goto exactly1;
1321024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)     && is8) goto exactly1;
1322024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)     && is8) goto exactly1;
1323024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)     && is8) goto exactly1;
1324024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSP)     && is8) goto exactly1;
1325024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBP)     && is8) goto exactly1;
1326024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSI)     && is8) goto exactly1;
1327024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDI)     && is8) goto exactly1;
1328024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R8)      && is8) goto exactly1;
1329024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R9)      && is8) goto exactly1;
1330024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R10)     && is8) goto exactly1;
1331024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R11)     && is8) goto exactly1;
1332024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R12)     && is8) goto exactly1;
1333024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R13)     && is8) goto exactly1;
1334024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R14)     && is8) goto exactly1;
1335024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R15)     && is8) goto exactly1;
1336024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RIP)     && is8) goto exactly1;
1337024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_OP)   && is8) goto none;
1338024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP1) && is8) goto none;
1339024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_DEP2) && is8) goto none;
1340024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CC_NDEP) && is8) goto none;
1341024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(DFLAG)   && is8) goto none;
1342024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(IDFLAG)  && is8) goto none;
1343024598e40c84666cc311a42c256bbf880db3ac99sewardj
1344024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Partial accesses to integer registers */
1345024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)     && is421) {         o -= 0; goto contains_o; }
1346024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RAX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1347024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)     && is421) {         o -= 0; goto contains_o; }
1348024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RCX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1349024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)     && is421) {         o -= 0; goto contains_o; }
1350024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1351024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)     && is421) {         o -= 0; goto contains_o; }
1352024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBX)+1   && is421) { o -= 1; o -= 0; goto contains_o; }
1353024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RBP)     && is421) {         o -= 0; goto contains_o; }
1354024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RSI)     && is421) {         o -= 0; goto contains_o; }
1355024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RDI)     && is421) {         o -= 0; goto contains_o; }
1356024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R8)      && is421) {         o -= 0; goto contains_o; }
1357024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R9)      && is421) {         o -= 0; goto contains_o; }
1358024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R10)     && is421) {         o -= 0; goto contains_o; }
1359024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R11)     && is421) {         o -= 0; goto contains_o; }
1360024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R12)     && is421) {         o -= 0; goto contains_o; }
1361024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R13)     && is421) {         o -= 0; goto contains_o; }
1362024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R14)     && is421) {         o -= 0; goto contains_o; }
1363024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(R15)     && is421) {         o -= 0; goto contains_o; }
1364024598e40c84666cc311a42c256bbf880db3ac99sewardj
1365024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Segment related guff */
1366024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FS_ZERO) && is8) goto exactly1;
1367024598e40c84666cc311a42c256bbf880db3ac99sewardj
1368024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1369024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(SSEROUND) && is8) goto none;
1370024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND)  && is8) goto none;
1371024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)   && sz == 4) goto none;
1372024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FTOP)     && sz == 4) goto none;
1373024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPTAG)    && is8) goto none;
1374024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FC3210)   && is8) goto none;
1375024598e40c84666cc311a42c256bbf880db3ac99sewardj
1376024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* xmm registers, including arbitrary sub-parts */
1377024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM0)  && o+sz <= GOF(XMM0)+16)  goto none;
1378024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM1)  && o+sz <= GOF(XMM1)+16)  goto none;
1379024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM2)  && o+sz <= GOF(XMM2)+16)  goto none;
1380024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM3)  && o+sz <= GOF(XMM3)+16)  goto none;
1381024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM4)  && o+sz <= GOF(XMM4)+16)  goto none;
1382024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM5)  && o+sz <= GOF(XMM5)+16)  goto none;
1383024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM6)  && o+sz <= GOF(XMM6)+16)  goto none;
1384024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM7)  && o+sz <= GOF(XMM7)+16)  goto none;
1385024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM8)  && o+sz <= GOF(XMM8)+16)  goto none;
1386024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM9)  && o+sz <= GOF(XMM9)+16)  goto none;
1387024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none;
1388024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none;
1389024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none;
1390024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none;
1391024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none;
1392024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none;
1393024598e40c84666cc311a42c256bbf880db3ac99sewardj
1394024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1395024598e40c84666cc311a42c256bbf880db3ac99sewardj      to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1396024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1397024598e40c84666cc311a42c256bbf880db3ac99sewardj
1398024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz);
1399024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1400024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1401024598e40c84666cc311a42c256bbf880db3ac99sewardj
1402024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc32 -------------------- */
1403024598e40c84666cc311a42c256bbf880db3ac99sewardj
1404024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc32)
1405024598e40c84666cc311a42c256bbf880db3ac99sewardj
1406024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1407024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestPPC32State,guest_##_fieldname))
1408024598e40c84666cc311a42c256bbf880db3ac99sewardj
1409024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1410024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1411024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1412024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8  = sz == 8;
1413024598e40c84666cc311a42c256bbf880db3ac99sewardj
1414024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1415024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_big_endian());
1416024598e40c84666cc311a42c256bbf880db3ac99sewardj
1417024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1418024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1419024598e40c84666cc311a42c256bbf880db3ac99sewardj
1420024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1421024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR0)  && is4) goto exactly1;
1422024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR1)  && is4) goto exactly1;
1423024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR2)  && is4) goto exactly1;
1424024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR3)  && is4) goto exactly1;
1425024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR4)  && is4) goto exactly1;
1426024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR5)  && is4) goto exactly1;
1427024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR6)  && is4) goto exactly1;
1428024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR7)  && is4) goto exactly1;
1429024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR8)  && is4) goto exactly1;
1430024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR9)  && is4) goto exactly1;
1431024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR10) && is4) goto exactly1;
1432024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR11) && is4) goto exactly1;
1433024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR12) && is4) goto exactly1;
1434024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR13) && is4) goto exactly1;
1435024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR14) && is4) goto exactly1;
1436024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR15) && is4) goto exactly1;
1437024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR16) && is4) goto exactly1;
1438024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR17) && is4) goto exactly1;
1439024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR18) && is4) goto exactly1;
1440024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR19) && is4) goto exactly1;
1441024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR20) && is4) goto exactly1;
1442024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR21) && is4) goto exactly1;
1443024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR22) && is4) goto exactly1;
1444024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR23) && is4) goto exactly1;
1445024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR24) && is4) goto exactly1;
1446024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR25) && is4) goto exactly1;
1447024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR26) && is4) goto exactly1;
1448024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR27) && is4) goto exactly1;
1449024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR28) && is4) goto exactly1;
1450024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR29) && is4) goto exactly1;
1451024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR30) && is4) goto exactly1;
1452024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR31) && is4) goto exactly1;
1453024598e40c84666cc311a42c256bbf880db3ac99sewardj
1454024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Misc integer reg and condition code accesses */
1455024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LR)        && is4) goto exactly1;
1456024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CTR)       && is4) goto exactly1;
1457024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA)       && is4) goto none;
1458024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA_AT_SC) && is4) goto none;
1459024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RESVN)     && is4) goto none;
1460024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TISTART)   && is4) goto none;
1461024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TILEN)     && is4) goto none;
1462024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(REDIR_SP)  && is4) goto none;
1463024598e40c84666cc311a42c256bbf880db3ac99sewardj
1464024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sz == 1) {
1465024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_SO))  goto none;
1466024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_OV))  goto none;
1467024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_CA))  goto none;
1468024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_BC))  goto none;
1469024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_321)) goto none;
1470024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_0))   goto none;
1471024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_321)) goto none;
1472024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_0))   goto none;
1473024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_321)) goto none;
1474024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_0))   goto none;
1475024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_321)) goto none;
1476024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_0))   goto none;
1477024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_321)) goto none;
1478024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_0))   goto none;
1479024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_321)) goto none;
1480024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_0))   goto none;
1481024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_321)) goto none;
1482024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_0))   goto none;
1483024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_321)) goto none;
1484024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_0))   goto none;
1485024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1486024598e40c84666cc311a42c256bbf880db3ac99sewardj
1487024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to FP registers */
1488024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR0)  && is8) goto none;
1489024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR1)  && is8) goto none;
1490024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR2)  && is8) goto none;
1491024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR3)  && is8) goto none;
1492024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR4)  && is8) goto none;
1493024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR5)  && is8) goto none;
1494024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR6)  && is8) goto none;
1495024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR7)  && is8) goto none;
1496024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR8)  && is8) goto none;
1497024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR9)  && is8) goto none;
1498024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR10) && is8) goto none;
1499024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR11) && is8) goto none;
1500024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR12) && is8) goto none;
1501024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR13) && is8) goto none;
1502024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR14) && is8) goto none;
1503024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR15) && is8) goto none;
1504024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR16) && is8) goto none;
1505024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR17) && is8) goto none;
1506024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR18) && is8) goto none;
1507024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR19) && is8) goto none;
1508024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR20) && is8) goto none;
1509024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR21) && is8) goto none;
1510024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR22) && is8) goto none;
1511024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR23) && is8) goto none;
1512024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR24) && is8) goto none;
1513024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR25) && is8) goto none;
1514024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR26) && is8) goto none;
1515024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR27) && is8) goto none;
1516024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR28) && is8) goto none;
1517024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR29) && is8) goto none;
1518024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR30) && is8) goto none;
1519024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR31) && is8) goto none;
1520024598e40c84666cc311a42c256bbf880db3ac99sewardj
1521024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1522024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND) && is4) goto none;
1523024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)  && is4) goto none;
1524024598e40c84666cc311a42c256bbf880db3ac99sewardj
1525024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Altivec registers */
1526024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR0)  && sz == 16) goto none;
1527024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR1)  && sz == 16) goto none;
1528024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR2)  && sz == 16) goto none;
1529024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR3)  && sz == 16) goto none;
1530024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR4)  && sz == 16) goto none;
1531024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR5)  && sz == 16) goto none;
1532024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR6)  && sz == 16) goto none;
1533024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR7)  && sz == 16) goto none;
1534024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR8)  && sz == 16) goto none;
1535024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR9)  && sz == 16) goto none;
1536024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR10) && sz == 16) goto none;
1537024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR11) && sz == 16) goto none;
1538024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR12) && sz == 16) goto none;
1539024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR13) && sz == 16) goto none;
1540024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR14) && sz == 16) goto none;
1541024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR15) && sz == 16) goto none;
1542024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR16) && sz == 16) goto none;
1543024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR17) && sz == 16) goto none;
1544024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR18) && sz == 16) goto none;
1545024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR19) && sz == 16) goto none;
1546024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR20) && sz == 16) goto none;
1547024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR21) && sz == 16) goto none;
1548024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR22) && sz == 16) goto none;
1549024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR23) && sz == 16) goto none;
1550024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR24) && sz == 16) goto none;
1551024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR25) && sz == 16) goto none;
1552024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR26) && sz == 16) goto none;
1553024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR27) && sz == 16) goto none;
1554024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR28) && sz == 16) goto none;
1555024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR29) && sz == 16) goto none;
1556024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR30) && sz == 16) goto none;
1557024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR31) && sz == 16) goto none;
1558024598e40c84666cc311a42c256bbf880db3ac99sewardj
1559024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz);
1560024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1561024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1562024598e40c84666cc311a42c256bbf880db3ac99sewardj
1563024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc64 -------------------- */
1564024598e40c84666cc311a42c256bbf880db3ac99sewardj
1565024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc64)
1566024598e40c84666cc311a42c256bbf880db3ac99sewardj
1567024598e40c84666cc311a42c256bbf880db3ac99sewardj#  define GOF(_fieldname) \
1568024598e40c84666cc311a42c256bbf880db3ac99sewardj      (offsetof(VexGuestPPC64State,guest_##_fieldname))
1569024598e40c84666cc311a42c256bbf880db3ac99sewardj
1570024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  o    = offset;
1571024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int  sz   = szB;
1572024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is4  = sz == 4;
1573024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool is8  = sz == 8;
1574024598e40c84666cc311a42c256bbf880db3ac99sewardj
1575024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sz > 0);
1576024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(host_is_big_endian());
1577024598e40c84666cc311a42c256bbf880db3ac99sewardj
1578024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set default state to "does not intersect any int register". */
1579024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)( iii, 0, sizeof(*iii) );
1580024598e40c84666cc311a42c256bbf880db3ac99sewardj
1581024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to integer registers */
1582024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR0)  && is8) goto exactly1;
1583024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR1)  && is8) goto exactly1;
1584024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR2)  && is8) goto exactly1;
1585024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR3)  && is8) goto exactly1;
1586024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR4)  && is8) goto exactly1;
1587024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR5)  && is8) goto exactly1;
1588024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR6)  && is8) goto exactly1;
1589024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR7)  && is8) goto exactly1;
1590024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR8)  && is8) goto exactly1;
1591024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR9)  && is8) goto exactly1;
1592024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR10) && is8) goto exactly1;
1593024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR11) && is8) goto exactly1;
1594024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR12) && is8) goto exactly1;
1595024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR13) && is8) goto exactly1;
1596024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR14) && is8) goto exactly1;
1597024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR15) && is8) goto exactly1;
1598024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR16) && is8) goto exactly1;
1599024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR17) && is8) goto exactly1;
1600024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR18) && is8) goto exactly1;
1601024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR19) && is8) goto exactly1;
1602024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR20) && is8) goto exactly1;
1603024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR21) && is8) goto exactly1;
1604024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR22) && is8) goto exactly1;
1605024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR23) && is8) goto exactly1;
1606024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR24) && is8) goto exactly1;
1607024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR25) && is8) goto exactly1;
1608024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR26) && is8) goto exactly1;
1609024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR27) && is8) goto exactly1;
1610024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR28) && is8) goto exactly1;
1611024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR29) && is8) goto exactly1;
1612024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR30) && is8) goto exactly1;
1613024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(GPR31) && is8) goto exactly1;
1614024598e40c84666cc311a42c256bbf880db3ac99sewardj
1615024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Misc integer reg and condition code accesses */
1616024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(LR)        && is8) goto exactly1;
1617024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CTR)       && is8) goto exactly1;
1618024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA)       && is8) goto none;
1619024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(CIA_AT_SC) && is8) goto none;
1620024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(RESVN)     && is8) goto none;
1621024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TISTART)   && is8) goto none;
1622024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(TILEN)     && is8) goto none;
1623024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(REDIR_SP)  && is8) goto none;
1624024598e40c84666cc311a42c256bbf880db3ac99sewardj
1625024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sz == 1) {
1626024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_SO))  goto none;
1627024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_OV))  goto none;
1628024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_CA))  goto none;
1629024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(XER_BC))  goto none;
1630024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_321)) goto none;
1631024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR0_0))   goto none;
1632024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_321)) goto none;
1633024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR1_0))   goto none;
1634024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_321)) goto none;
1635024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR2_0))   goto none;
1636024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_321)) goto none;
1637024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR3_0))   goto none;
1638024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_321)) goto none;
1639024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR4_0))   goto none;
1640024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_321)) goto none;
1641024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR5_0))   goto none;
1642024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_321)) goto none;
1643024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR6_0))   goto none;
1644024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_321)) goto none;
1645024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (o == GOF(CR7_0))   goto none;
1646024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1647024598e40c84666cc311a42c256bbf880db3ac99sewardj
1648024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Exact accesses to FP registers */
1649024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR0)  && is8) goto none;
1650024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR1)  && is8) goto none;
1651024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR2)  && is8) goto none;
1652024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR3)  && is8) goto none;
1653024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR4)  && is8) goto none;
1654024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR5)  && is8) goto none;
1655024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR6)  && is8) goto none;
1656024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR7)  && is8) goto none;
1657024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR8)  && is8) goto none;
1658024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR9)  && is8) goto none;
1659024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR10) && is8) goto none;
1660024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR11) && is8) goto none;
1661024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR12) && is8) goto none;
1662024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR13) && is8) goto none;
1663024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR14) && is8) goto none;
1664024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR15) && is8) goto none;
1665024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR16) && is8) goto none;
1666024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR17) && is8) goto none;
1667024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR18) && is8) goto none;
1668024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR19) && is8) goto none;
1669024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR20) && is8) goto none;
1670024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR21) && is8) goto none;
1671024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR22) && is8) goto none;
1672024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR23) && is8) goto none;
1673024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR24) && is8) goto none;
1674024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR25) && is8) goto none;
1675024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR26) && is8) goto none;
1676024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR27) && is8) goto none;
1677024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR28) && is8) goto none;
1678024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR29) && is8) goto none;
1679024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR30) && is8) goto none;
1680024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPR31) && is8) goto none;
1681024598e40c84666cc311a42c256bbf880db3ac99sewardj
1682024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* FP admin related */
1683024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(FPROUND) && is4) goto none;
1684024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(EMWARN)  && is4) goto none;
1685024598e40c84666cc311a42c256bbf880db3ac99sewardj
1686024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Altivec registers */
1687024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR0)  && sz == 16) goto none;
1688024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR1)  && sz == 16) goto none;
1689024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR2)  && sz == 16) goto none;
1690024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR3)  && sz == 16) goto none;
1691024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR4)  && sz == 16) goto none;
1692024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR5)  && sz == 16) goto none;
1693024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR6)  && sz == 16) goto none;
1694024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR7)  && sz == 16) goto none;
1695024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR8)  && sz == 16) goto none;
1696024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR9)  && sz == 16) goto none;
1697024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR10) && sz == 16) goto none;
1698024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR11) && sz == 16) goto none;
1699024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR12) && sz == 16) goto none;
1700024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR13) && sz == 16) goto none;
1701024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR14) && sz == 16) goto none;
1702024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR15) && sz == 16) goto none;
1703024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR16) && sz == 16) goto none;
1704024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR17) && sz == 16) goto none;
1705024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR18) && sz == 16) goto none;
1706024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR19) && sz == 16) goto none;
1707024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR20) && sz == 16) goto none;
1708024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR21) && sz == 16) goto none;
1709024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR22) && sz == 16) goto none;
1710024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR23) && sz == 16) goto none;
1711024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR24) && sz == 16) goto none;
1712024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR25) && sz == 16) goto none;
1713024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR26) && sz == 16) goto none;
1714024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR27) && sz == 16) goto none;
1715024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR28) && sz == 16) goto none;
1716024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR29) && sz == 16) goto none;
1717024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR30) && sz == 16) goto none;
1718024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (o == GOF(VR31) && sz == 16) goto none;
1719024598e40c84666cc311a42c256bbf880db3ac99sewardj
1720024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz);
1721024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1722024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef GOF
1723024598e40c84666cc311a42c256bbf880db3ac99sewardj
1724024598e40c84666cc311a42c256bbf880db3ac99sewardj
1725024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
1726024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "FIXME: not implemented for this architecture"
1727024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
1728024598e40c84666cc311a42c256bbf880db3ac99sewardj
1729024598e40c84666cc311a42c256bbf880db3ac99sewardj  exactly1:
1730024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = -1;
1731024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1732024598e40c84666cc311a42c256bbf880db3ac99sewardj  none:
1733024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = 0;
1734024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1735024598e40c84666cc311a42c256bbf880db3ac99sewardj  contains_o:
1736024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(o >= 0 && 0 == (o % sizeof(UWord)));
1737024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->n_offsets = 1;
1738024598e40c84666cc311a42c256bbf880db3ac99sewardj   iii->offsets[0] = o;
1739024598e40c84666cc311a42c256bbf880db3ac99sewardj   return;
1740024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1741024598e40c84666cc311a42c256bbf880db3ac99sewardj
1742024598e40c84666cc311a42c256bbf880db3ac99sewardj
1743024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Does 'arr' describe an indexed guest state section containing host
1744024598e40c84666cc311a42c256bbf880db3ac99sewardj   words, that we want to shadow? */
1745024598e40c84666cc311a42c256bbf880db3ac99sewardj
1746024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg_array ( IRRegArray* arr )
1747024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1748024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------------- x86 --------------------- */
1749024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86)
1750024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 tag array. */
1751024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0])
1752024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I8 && arr->nElems == 8)
1753024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1754024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 register array. */
1755024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0])
1756024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_F64 && arr->nElems == 8)
1757024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1758024598e40c84666cc311a42c256bbf880db3ac99sewardj
1759024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(x86): unhandled: ");
1760024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1761024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1762024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1763024598e40c84666cc311a42c256bbf880db3ac99sewardj
1764024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- amd64 -------------------- */
1765024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64)
1766024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 tag array. */
1767024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0])
1768024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I8 && arr->nElems == 8)
1769024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1770024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The x87 register array. */
1771024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0])
1772024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_F64 && arr->nElems == 8)
1773024598e40c84666cc311a42c256bbf880db3ac99sewardj      return False;
1774024598e40c84666cc311a42c256bbf880db3ac99sewardj
1775024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: ");
1776024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1777024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1778024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1779024598e40c84666cc311a42c256bbf880db3ac99sewardj
1780024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc32 -------------------- */
1781024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc32)
1782024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The redir stack. */
1783024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0])
1784024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I32
1785024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE)
1786024598e40c84666cc311a42c256bbf880db3ac99sewardj      return True;
1787024598e40c84666cc311a42c256bbf880db3ac99sewardj
1788024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: ");
1789024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1790024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1791024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1792024598e40c84666cc311a42c256bbf880db3ac99sewardj
1793024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* -------------------- ppc64 -------------------- */
1794024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_ppc64)
1795024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* The redir stack. */
1796024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0])
1797024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->elemTy == Ity_I64
1798024598e40c84666cc311a42c256bbf880db3ac99sewardj       && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE)
1799024598e40c84666cc311a42c256bbf880db3ac99sewardj      return True;
1800024598e40c84666cc311a42c256bbf880db3ac99sewardj
1801024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: ");
1802024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRRegArray(arr);
1803024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("\n");
1804024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
1805024598e40c84666cc311a42c256bbf880db3ac99sewardj
1806024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
1807024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "FIXME: not implemented for this architecture"
1808024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
1809024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1810024598e40c84666cc311a42c256bbf880db3ac99sewardj
1811024598e40c84666cc311a42c256bbf880db3ac99sewardj
1812024598e40c84666cc311a42c256bbf880db3ac99sewardj// END move this uglyness to pc_machine.c
1813024598e40c84666cc311a42c256bbf880db3ac99sewardj
1814024598e40c84666cc311a42c256bbf880db3ac99sewardj/* returns True iff given slice exactly matches an int reg.  Merely
1815024598e40c84666cc311a42c256bbf880db3ac99sewardj   a convenience wrapper around get_IntRegInfo. */
1816024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg ( Int offset, Int szB )
1817024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1818024598e40c84666cc311a42c256bbf880db3ac99sewardj   IntRegInfo iii;
1819024598e40c84666cc311a42c256bbf880db3ac99sewardj   get_IntRegInfo( &iii, offset, szB );
1820024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
1821024598e40c84666cc311a42c256bbf880db3ac99sewardj   return iii.n_offsets == -1;
1822024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1823024598e40c84666cc311a42c256bbf880db3ac99sewardj
1824024598e40c84666cc311a42c256bbf880db3ac99sewardj/* these assume guest and host have the same endianness and
1825024598e40c84666cc311a42c256bbf880db3ac99sewardj   word size (probably). */
1826024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UWord get_guest_intreg ( ThreadId tid, Int shadowNo,
1827024598e40c84666cc311a42c256bbf880db3ac99sewardj                                OffT offset, SizeT size )
1828024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1829024598e40c84666cc311a42c256bbf880db3ac99sewardj   UChar tmp[ 2 + sizeof(UWord) ];
1830024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(size == sizeof(UWord));
1831024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (offset % sizeof(UWord)));
1832024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(memset)(tmp, 0, sizeof(tmp));
1833024598e40c84666cc311a42c256bbf880db3ac99sewardj   tmp[0] = 0x31;
1834024598e40c84666cc311a42c256bbf880db3ac99sewardj   tmp[ sizeof(tmp)-1 ] = 0x27;
1835024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size);
1836024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tmp[0] == 0x31);
1837024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27);
1838024598e40c84666cc311a42c256bbf880db3ac99sewardj   return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */
1839024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1840024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void put_guest_intreg ( ThreadId tid, Int shadowNo,
1841024598e40c84666cc311a42c256bbf880db3ac99sewardj                               OffT offset, SizeT size, UWord w )
1842024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1843024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(size == sizeof(UWord));
1844024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0 == (offset % sizeof(UWord)));
1845024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(set_shadow_regs_area)(tid, shadowNo, offset, size,
1846024598e40c84666cc311a42c256bbf880db3ac99sewardj                             (const UChar*)&w);
1847024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1848024598e40c84666cc311a42c256bbf880db3ac99sewardj
1849024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Initialise the integer shadow registers to UNKNOWN.  This is a bit
1850024598e40c84666cc311a42c256bbf880db3ac99sewardj   of a nasty kludge, but it does mean we don't need to know which
1851024598e40c84666cc311a42c256bbf880db3ac99sewardj   registers we really need to initialise -- simply assume that all
1852024598e40c84666cc311a42c256bbf880db3ac99sewardj   integer registers will be naturally aligned w.r.t. the start of the
1853024598e40c84666cc311a42c256bbf880db3ac99sewardj   guest state, and fill in all possible entries. */
1854024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_shadow_registers ( ThreadId tid )
1855024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1856024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i, wordSzB = sizeof(UWord);
1857024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < MC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) {
1858024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN );
1859024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1860024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1861024598e40c84666cc311a42c256bbf880db3ac99sewardj
1862024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void post_reg_write_nonptr ( ThreadId tid, OffT offset, SizeT size )
1863024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1864024598e40c84666cc311a42c256bbf880db3ac99sewardj   // syscall_return: Default is non-pointer.  If it really is a pointer
1865024598e40c84666cc311a42c256bbf880db3ac99sewardj   // (eg. for mmap()), SK_(post_syscall) sets it again afterwards.
1866024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1867024598e40c84666cc311a42c256bbf880db3ac99sewardj   // clientreq_return: All the global client requests return non-pointers
1868024598e40c84666cc311a42c256bbf880db3ac99sewardj   // (except possibly CLIENT_CALL[0123], but they're handled by
1869024598e40c84666cc311a42c256bbf880db3ac99sewardj   // post_reg_write_clientcall, not here).
1870024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1871024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1872024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR );
1873024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
1874024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
1875024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1876024598e40c84666cc311a42c256bbf880db3ac99sewardj   //   VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR );
1877024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1878024598e40c84666cc311a42c256bbf880db3ac99sewardj
1879024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void post_reg_write_nonptr_or_unknown ( ThreadId tid,
1880024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               OffT offset, SizeT size )
1881024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1882024598e40c84666cc311a42c256bbf880db3ac99sewardj   // deliver_signal: called from two places; one sets the reg to zero, the
1883024598e40c84666cc311a42c256bbf880db3ac99sewardj   // other sets the stack pointer.
1884024598e40c84666cc311a42c256bbf880db3ac99sewardj   //
1885024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1886024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg(
1887024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, 1/*shadowno*/, offset, size,
1888024598e40c84666cc311a42c256bbf880db3ac99sewardj         (UWord)nonptr_or_unknown(
1889024598e40c84666cc311a42c256bbf880db3ac99sewardj                   get_guest_intreg( tid, 0/*shadowno*/,
1890024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     offset, size )));
1891024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
1892024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
1893024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1894024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1895024598e40c84666cc311a42c256bbf880db3ac99sewardj
1896024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_reg_write_demux ( CorePart part, ThreadId tid,
1897024598e40c84666cc311a42c256bbf880db3ac99sewardj                              OffT guest_state_offset, SizeT size)
1898024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1899024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0)
1900024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
1901024598e40c84666cc311a42c256bbf880db3ac99sewardj               (Int)tid, (Int)part,
1902024598e40c84666cc311a42c256bbf880db3ac99sewardj              guest_state_offset, size);
1903024598e40c84666cc311a42c256bbf880db3ac99sewardj   switch (part) {
1904024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreStartup:
1905024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* This is a bit of a kludge since for any Vg_CoreStartup
1906024598e40c84666cc311a42c256bbf880db3ac99sewardj            event we overwrite the entire shadow register set.  But
1907024598e40c84666cc311a42c256bbf880db3ac99sewardj            that's ok - we're only called once with
1908024598e40c84666cc311a42c256bbf880db3ac99sewardj            part==Vg_CoreStartup event, and in that case the supplied
1909024598e40c84666cc311a42c256bbf880db3ac99sewardj            offset & size cover the entire guest state anyway. */
1910024598e40c84666cc311a42c256bbf880db3ac99sewardj         init_shadow_registers(tid);
1911024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
1912024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreSysCall:
1913024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ p_r_w    -> NONPTR\n");
1914024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr( tid, guest_state_offset, size );
1915024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
1916024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreClientReq:
1917024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr( tid, guest_state_offset, size );
1918024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
1919024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Vg_CoreSignal:
1920024598e40c84666cc311a42c256bbf880db3ac99sewardj         post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size );
1921024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
1922024598e40c84666cc311a42c256bbf880db3ac99sewardj      default:
1923024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(0);
1924024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1925024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1926024598e40c84666cc311a42c256bbf880db3ac99sewardj
1927024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_reg_write_clientcall(ThreadId tid, OffT guest_state_offset,
1928024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 SizeT size, Addr f )
1929024598e40c84666cc311a42c256bbf880db3ac99sewardj{
1930024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWord p;
1931024598e40c84666cc311a42c256bbf880db3ac99sewardj
1932024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Having to do this is a bit nasty...
1933024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (f == (Addr)h_replace_malloc
1934024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace___builtin_new
1935024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace___builtin_vec_new
1936024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_calloc
1937024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_memalign
1938024598e40c84666cc311a42c256bbf880db3ac99sewardj       || f == (Addr)h_replace_realloc)
1939024598e40c84666cc311a42c256bbf880db3ac99sewardj   {
1940024598e40c84666cc311a42c256bbf880db3ac99sewardj      // We remembered the last added segment;  make sure it's the right one.
1941024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* What's going on: at this point, the scheduler has just called
1942024598e40c84666cc311a42c256bbf880db3ac99sewardj         'f' -- one of our malloc replacement functions -- and it has
1943024598e40c84666cc311a42c256bbf880db3ac99sewardj         returned.  The return value has been written to the guest
1944024598e40c84666cc311a42c256bbf880db3ac99sewardj         state of thread 'tid', offset 'guest_state_offset' length
1945024598e40c84666cc311a42c256bbf880db3ac99sewardj         'size'.  We need to look at that return value and set the
1946024598e40c84666cc311a42c256bbf880db3ac99sewardj         shadow return value accordingly.  The shadow return value
1947024598e40c84666cc311a42c256bbf880db3ac99sewardj         required is handed to us "under the counter" through the
1948024598e40c84666cc311a42c256bbf880db3ac99sewardj         global variable 'last_seg_added'.  This is all very ugly, not
1949024598e40c84666cc311a42c256bbf880db3ac99sewardj         to mention, non-thread-safe should V ever become
1950024598e40c84666cc311a42c256bbf880db3ac99sewardj         multithreaded. */
1951024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* assert the place where the return value is is a legit int reg */
1952024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(is_integer_guest_reg(guest_state_offset, size));
1953024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Now we need to look at the returned value, to see whether the
1954024598e40c84666cc311a42c256bbf880db3ac99sewardj         malloc succeeded or not. */
1955024598e40c84666cc311a42c256bbf880db3ac99sewardj      p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size);
1956024598e40c84666cc311a42c256bbf880db3ac99sewardj      if ((UWord)NULL == p) {
1957024598e40c84666cc311a42c256bbf880db3ac99sewardj         // if alloc failed, eg. realloc on bogus pointer
1958024598e40c84666cc311a42c256bbf880db3ac99sewardj         put_guest_intreg(tid, 1/*first-shadow*/,
1959024598e40c84666cc311a42c256bbf880db3ac99sewardj                          guest_state_offset, size, (UWord)NONPTR );
1960024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
1961024598e40c84666cc311a42c256bbf880db3ac99sewardj         // alloc didn't fail.  Check we have the correct segment.
1962024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(p == last_seg_added->addr);
1963024598e40c84666cc311a42c256bbf880db3ac99sewardj         put_guest_intreg(tid, 1/*first-shadow*/,
1964024598e40c84666cc311a42c256bbf880db3ac99sewardj                          guest_state_offset, size, (UWord)last_seg_added );
1965024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
1966024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1967024598e40c84666cc311a42c256bbf880db3ac99sewardj   else if (f == (Addr)h_replace_free
1968024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)h_replace___builtin_delete
1969024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)h_replace___builtin_vec_delete
1970024598e40c84666cc311a42c256bbf880db3ac99sewardj   //            || f == (Addr)VG_(cli_block_size)
1971024598e40c84666cc311a42c256bbf880db3ac99sewardj            || f == (Addr)VG_(message))
1972024598e40c84666cc311a42c256bbf880db3ac99sewardj   {
1973024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Probably best to set the (non-existent!) return value to
1974024598e40c84666cc311a42c256bbf880db3ac99sewardj      // non-pointer.
1975024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(is_integer_guest_reg(guest_state_offset, size));
1976024598e40c84666cc311a42c256bbf880db3ac99sewardj      put_guest_intreg(tid, 1/*first-shadow*/,
1977024598e40c84666cc311a42c256bbf880db3ac99sewardj                       guest_state_offset, size, (UWord)NONPTR );
1978024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1979024598e40c84666cc311a42c256bbf880db3ac99sewardj   else {
1980024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Anything else, probably best to set return value to non-pointer.
1981024598e40c84666cc311a42c256bbf880db3ac99sewardj      //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN);
1982024598e40c84666cc311a42c256bbf880db3ac99sewardj      Char fbuf[100];
1983024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("f = %#lx\n", f);
1984024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(get_fnname)(f, fbuf, 100);
1985024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("name = %s\n", fbuf);
1986024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("argh: clientcall");
1987024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
1988024598e40c84666cc311a42c256bbf880db3ac99sewardj}
1989024598e40c84666cc311a42c256bbf880db3ac99sewardj
1990024598e40c84666cc311a42c256bbf880db3ac99sewardj
1991024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/
1992024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--- Sanity checking                                              ---*/
1993024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/
1994024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
1995024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* Check that nobody has spuriously claimed that the first or last 16
1996024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    pages (64 KB) of address space have become accessible.  Failure of
1997024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    the following do not per se indicate an internal consistency
1998024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    problem, but they are so likely to that we really want to know
1999024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    about it if so. */
2000024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool pc_replace_cheap_sanity_check) ( void )
2001024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2002024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (IS_DISTINGUISHED_SM(primary_map[0])
2003024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz        /* kludge: kernel drops a page up at top of address range for
2004024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz           magic "optimized syscalls", so we can no longer check the
2005024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz           highest page */
2006024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz        /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
2007024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       )
2008024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
2009024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    else
2010024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return False;
2011024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2012024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2013024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool SK_(expensive_sanity_check) ( void )
2014024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2015024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    Int i;
2016024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2017024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    /* Make sure nobody changed the distinguished secondary. */
2018024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    for (i = 0; i < SEC_MAP_WORDS; i++)
2019024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       if (distinguished_secondary_map.vseg[i] != UNKNOWN)
2020024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz          return False;
2021024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
2022024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return True;
2023024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2024024598e40c84666cc311a42c256bbf880db3ac99sewardj
2025024598e40c84666cc311a42c256bbf880db3ac99sewardj
2026024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2027024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- System calls                                                 ---*/
2028024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2029024598e40c84666cc311a42c256bbf880db3ac99sewardj
2030024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_syscall ( ThreadId tid, UInt sysno )
2031024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2032024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* we don't do anything at the pre-syscall point */
2033024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2034024598e40c84666cc311a42c256bbf880db3ac99sewardj
2035024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The post-syscall table is a table of pairs (number, flag).
2036024598e40c84666cc311a42c256bbf880db3ac99sewardj
2037024598e40c84666cc311a42c256bbf880db3ac99sewardj   'flag' is only ever zero or one.  If it is zero, it indicates that
2038024598e40c84666cc311a42c256bbf880db3ac99sewardj   default handling for that syscall is required -- namely that the
2039024598e40c84666cc311a42c256bbf880db3ac99sewardj   syscall is deemed to return NONPTR.  This is the case for the vast
2040024598e40c84666cc311a42c256bbf880db3ac99sewardj   majority of syscalls.  If it is one then some special
2041024598e40c84666cc311a42c256bbf880db3ac99sewardj   syscall-specific handling is is required.  No further details of it
2042024598e40c84666cc311a42c256bbf880db3ac99sewardj   are stored in the table.
2043024598e40c84666cc311a42c256bbf880db3ac99sewardj
2044024598e40c84666cc311a42c256bbf880db3ac99sewardj   On Linux, 'number' is a __NR_xxx constant.
2045024598e40c84666cc311a42c256bbf880db3ac99sewardj
2046024598e40c84666cc311a42c256bbf880db3ac99sewardj   On AIX5, 'number' is an Int*, which points to the Int variable
2047024598e40c84666cc311a42c256bbf880db3ac99sewardj   holding the currently assigned number for this syscall.
2048024598e40c84666cc311a42c256bbf880db3ac99sewardj
2049024598e40c84666cc311a42c256bbf880db3ac99sewardj   When querying the table, we compare the supplied syscall number
2050024598e40c84666cc311a42c256bbf880db3ac99sewardj   with the 'number' field (directly on Linux, after dereferencing on
2051024598e40c84666cc311a42c256bbf880db3ac99sewardj   AIX5), to find the relevant entry.  This requires a linear search
2052024598e40c84666cc311a42c256bbf880db3ac99sewardj   of the table.  To stop the costs getting too high, the table is
2053024598e40c84666cc311a42c256bbf880db3ac99sewardj   incrementally rearranged after each search, to move commonly
2054024598e40c84666cc311a42c256bbf880db3ac99sewardj   requested items a bit closer to the front.
2055024598e40c84666cc311a42c256bbf880db3ac99sewardj
2056024598e40c84666cc311a42c256bbf880db3ac99sewardj   The table is built once, the first time it is used.  After that we
2057024598e40c84666cc311a42c256bbf880db3ac99sewardj   merely query it (and reorder the entries as a result). */
2058024598e40c84666cc311a42c256bbf880db3ac99sewardj
2059024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic XArray* /* of UWordPair */ post_syscall_table = NULL;
2060024598e40c84666cc311a42c256bbf880db3ac99sewardj
2061024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void setup_post_syscall_table ( void )
2062024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2063024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(!post_syscall_table);
2064024598e40c84666cc311a42c256bbf880db3ac99sewardj   post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1",
2065024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    VG_(free), sizeof(UWordPair) );
2066024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(post_syscall_table);
2067024598e40c84666cc311a42c256bbf880db3ac99sewardj
2068024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------- LINUX --------------- */
2069024598e40c84666cc311a42c256bbf880db3ac99sewardj
2070024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGO_linux)
2071024598e40c84666cc311a42c256bbf880db3ac99sewardj
2072024598e40c84666cc311a42c256bbf880db3ac99sewardj#     define ADD(_flag, _syscallname) \
2073024598e40c84666cc311a42c256bbf880db3ac99sewardj         do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2074024598e40c84666cc311a42c256bbf880db3ac99sewardj              VG_(addToXA)( post_syscall_table, &p ); \
2075024598e40c84666cc311a42c256bbf880db3ac99sewardj         } while (0)
2076024598e40c84666cc311a42c256bbf880db3ac99sewardj
2077024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* These ones definitely don't return pointers.  They're not
2078024598e40c84666cc311a42c256bbf880db3ac99sewardj         particularly grammatical, either. */
2079024598e40c84666cc311a42c256bbf880db3ac99sewardj
2080024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR__llseek)
2081024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__llseek);
2082024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2083024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__sysctl);
2084024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR__newselect)
2085024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR__newselect);
2086024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2087024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_accept)
2088024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_accept);
2089024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2090024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_access);
2091024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_bind)
2092024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_bind);
2093024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2094024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_chdir)
2095024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chdir);
2096024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2097024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chmod);
2098024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_chown);
2099024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clock_getres);
2100024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clock_gettime);
2101024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_clone);
2102024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_close);
2103024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_connect)
2104024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_connect);
2105024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2106024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_dup);
2107024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_dup2);
2108024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_execve); /* presumably we see this because the call failed? */
2109024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_exit); /* hmm, why are we still alive? */
2110024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_exit_group);
2111024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fadvise64);
2112024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchmod);
2113024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchown);
2114024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fchown32)
2115024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fchown32);
2116024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2117024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fcntl);
2118024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fcntl64)
2119024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fcntl64);
2120024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2121024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fdatasync);
2122024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstat);
2123024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_fstat64)
2124024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstat64);
2125024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2126024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fstatfs);
2127024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_fsync);
2128024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ftruncate);
2129024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_ftruncate64)
2130024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ftruncate64);
2131024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2132024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_futex);
2133024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getcwd);
2134024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getdents); // something to do with teeth
2135024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getdents64);
2136024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getegid);
2137024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getegid32)
2138024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getegid32);
2139024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2140024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_geteuid);
2141024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_geteuid32)
2142024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_geteuid32);
2143024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2144024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getgid);
2145024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getgid32)
2146024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getgid32);
2147024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2148024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getitimer);
2149024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getpeername)
2150024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getpeername);
2151024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2152024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getpid);
2153024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getppid);
2154024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getresgid);
2155024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getresuid);
2156024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getrlimit);
2157024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getsockname)
2158024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getsockname);
2159024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2160024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getsockopt)
2161024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getsockopt);
2162024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2163024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_gettimeofday);
2164024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getuid);
2165024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_getuid32)
2166024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getuid32);
2167024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2168024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_getxattr);
2169024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_inotify_init);
2170024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ioctl); // ioctl -- assuming no pointers returned
2171024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_kill);
2172024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_link);
2173024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_listen)
2174024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_listen);
2175024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2176024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lseek);
2177024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lstat);
2178024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_lstat64)
2179024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_lstat64);
2180024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2181024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_madvise);
2182024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_mkdir);
2183024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_mprotect);
2184024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_munmap); // die_mem_munmap already called, segment remove);
2185024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_open);
2186024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pipe);
2187024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_poll);
2188024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pread64);
2189024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_pwrite64);
2190024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_read);
2191024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_readlink);
2192024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_readv);
2193024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_recvfrom)
2194024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_recvfrom);
2195024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2196024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_recvmsg)
2197024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_recvmsg);
2198024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2199024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rename);
2200024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rmdir);
2201024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigaction);
2202024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigprocmask);
2203024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_rt_sigreturn); /* not sure if we should see this or not */
2204024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_get_priority_max);
2205024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_get_priority_min);
2206024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_getparam);
2207024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_getscheduler);
2208024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_setscheduler);
2209024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sched_yield);
2210024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_select);
2211024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_sendto)
2212024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sendto);
2213024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2214024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_robust_list);
2215024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_set_thread_area)
2216024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_thread_area);
2217024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2218024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_set_tid_address);
2219024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setitimer);
2220024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setrlimit);
2221024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setsid);
2222024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_setsockopt)
2223024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_setsockopt);
2224024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2225024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmctl)
2226024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shmctl);
2227024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shmdt);
2228024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2229024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shutdown)
2230024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_shutdown);
2231024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2232024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_socket)
2233024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_socket);
2234024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2235024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_socketcall)
2236024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */
2237024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2238024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_statfs64)
2239024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_statfs64);
2240024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2241024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_sigreturn)
2242024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sigreturn); /* not sure if we should see this or not */
2243024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2244024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_stat64)
2245024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_stat64);
2246024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2247024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_stat);
2248024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_statfs);
2249024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_symlink);
2250024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_sysinfo);
2251024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_tgkill);
2252024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_time);
2253024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_times);
2254024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_truncate);
2255024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_truncate64)
2256024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_truncate64);
2257024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2258024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_ugetrlimit)
2259024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_ugetrlimit);
2260024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2261024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_umask);
2262024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_uname);
2263024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_unlink);
2264024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_utime);
2265024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_waitpid)
2266024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_waitpid);
2267024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2268024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_wait4);
2269024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_write);
2270024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_writev);
2271024598e40c84666cc311a42c256bbf880db3ac99sewardj
2272024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Whereas the following need special treatment */
2273024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_arch_prctl)
2274024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_arch_prctl);
2275024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2276024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_brk);
2277024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_mmap);
2278024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_mmap2)
2279024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_mmap2);
2280024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2281024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmat)
2282024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_shmat);
2283024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2284024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(__NR_shmget)
2285024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_shmget);
2286024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2287024598e40c84666cc311a42c256bbf880db3ac99sewardj
2288024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* --------------- AIX5 --------------- */
2289024598e40c84666cc311a42c256bbf880db3ac99sewardj
2290024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGO_aix5)
2291024598e40c84666cc311a42c256bbf880db3ac99sewardj
2292024598e40c84666cc311a42c256bbf880db3ac99sewardj#     define ADD(_flag, _syscallname) \
2293024598e40c84666cc311a42c256bbf880db3ac99sewardj         do { \
2294024598e40c84666cc311a42c256bbf880db3ac99sewardj            UWordPair p; \
2295024598e40c84666cc311a42c256bbf880db3ac99sewardj            if ((_syscallname) != __NR_AIX5_UNKNOWN) { \
2296024598e40c84666cc311a42c256bbf880db3ac99sewardj               p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \
2297024598e40c84666cc311a42c256bbf880db3ac99sewardj               VG_(addToXA)( post_syscall_table, &p ); \
2298024598e40c84666cc311a42c256bbf880db3ac99sewardj            } \
2299024598e40c84666cc311a42c256bbf880db3ac99sewardj         } while (0)
2300024598e40c84666cc311a42c256bbf880db3ac99sewardj
2301024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* Just a minimal set of handlers, enough to make
2302024598e40c84666cc311a42c256bbf880db3ac99sewardj         a 32- and 64-bit hello-world program run. */
2303024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_AIX5___loadx); /* not sure what to do here */
2304024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5__exit);
2305024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_access);
2306024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_getgidx);
2307024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_getuidx);
2308024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kfcntl);
2309024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kioctl);
2310024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(1, __NR_AIX5_kload); /* not sure what to do here */
2311024598e40c84666cc311a42c256bbf880db3ac99sewardj      ADD(0, __NR_AIX5_kwrite);
2312024598e40c84666cc311a42c256bbf880db3ac99sewardj
2313024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
2314024598e40c84666cc311a42c256bbf880db3ac99sewardj#     error "Unsupported OS"
2315024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2316024598e40c84666cc311a42c256bbf880db3ac99sewardj
2317024598e40c84666cc311a42c256bbf880db3ac99sewardj#  undef ADD
2318024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2319024598e40c84666cc311a42c256bbf880db3ac99sewardj
2320024598e40c84666cc311a42c256bbf880db3ac99sewardj
2321024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_syscall ( ThreadId tid, UInt sysno, SysRes res )
2322024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2323024598e40c84666cc311a42c256bbf880db3ac99sewardj   Word i, n;
2324024598e40c84666cc311a42c256bbf880db3ac99sewardj   UWordPair* pair;
2325024598e40c84666cc311a42c256bbf880db3ac99sewardj
2326024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (!post_syscall_table)
2327024598e40c84666cc311a42c256bbf880db3ac99sewardj      setup_post_syscall_table();
2328024598e40c84666cc311a42c256bbf880db3ac99sewardj
2329024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* search for 'sysno' in the post_syscall_table */
2330024598e40c84666cc311a42c256bbf880db3ac99sewardj   n = VG_(sizeXA)( post_syscall_table );
2331024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < n; i++) {
2332024598e40c84666cc311a42c256bbf880db3ac99sewardj      pair = VG_(indexXA)( post_syscall_table, i );
2333024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(VGO_linux)
2334024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (pair->uw1 == (UWord)sysno)
2335024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2336024598e40c84666cc311a42c256bbf880db3ac99sewardj#     elif defined(VGO_aix5)
2337024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (*(Int*)(pair->uw1) == (Int)sysno)
2338024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
2339024598e40c84666cc311a42c256bbf880db3ac99sewardj#     else
2340024598e40c84666cc311a42c256bbf880db3ac99sewardj#        error "Unsupported OS"
2341024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2342024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2343024598e40c84666cc311a42c256bbf880db3ac99sewardj
2344024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0 && i <= n);
2345024598e40c84666cc311a42c256bbf880db3ac99sewardj
2346024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i == n) {
2347024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("sysno == %u\n", sysno);
2348024598e40c84666cc311a42c256bbf880db3ac99sewardj#     if defined(VGO_aix5)
2349024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("syscallnm == %s\n",
2350024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(aix5_sysno_to_sysname)(sysno));
2351024598e40c84666cc311a42c256bbf880db3ac99sewardj#     endif
2352024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("unhandled syscall");
2353024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2354024598e40c84666cc311a42c256bbf880db3ac99sewardj
2355024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* So we found the relevant entry.  Move it one step
2356024598e40c84666cc311a42c256bbf880db3ac99sewardj      forward so as to speed future accesses to it. */
2357024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (i > 0) {
2358024598e40c84666cc311a42c256bbf880db3ac99sewardj      UWordPair tmp, *p, *q;
2359024598e40c84666cc311a42c256bbf880db3ac99sewardj      p = VG_(indexXA)( post_syscall_table, i-1 );
2360024598e40c84666cc311a42c256bbf880db3ac99sewardj      q = VG_(indexXA)( post_syscall_table, i-0 );
2361024598e40c84666cc311a42c256bbf880db3ac99sewardj      tmp = *p;
2362024598e40c84666cc311a42c256bbf880db3ac99sewardj      *p = *q;
2363024598e40c84666cc311a42c256bbf880db3ac99sewardj      *q = tmp;
2364024598e40c84666cc311a42c256bbf880db3ac99sewardj      i--;
2365024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2366024598e40c84666cc311a42c256bbf880db3ac99sewardj
2367024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Deal with the common case */
2368024598e40c84666cc311a42c256bbf880db3ac99sewardj   pair = VG_(indexXA)( post_syscall_table, i );
2369024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pair->uw2 == 0) {
2370024598e40c84666cc311a42c256bbf880db3ac99sewardj     /* the common case */
2371024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)(
2372024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, /* retval */ (UWord)NONPTR, 0,
2373024598e40c84666cc311a42c256bbf880db3ac99sewardj              /* error */  (UWord)NONPTR, 0
2374024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
2375024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2376024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2377024598e40c84666cc311a42c256bbf880db3ac99sewardj
2378024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Special handling for all remaining cases */
2379024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pair->uw2 == 1);
2380024598e40c84666cc311a42c256bbf880db3ac99sewardj
2381024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_arch_prctl)
2382024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_arch_prctl) {
2383024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* This is nasty.  On amd64-linux, arch_prctl may write a
2384024598e40c84666cc311a42c256bbf880db3ac99sewardj         value to guest_FS_ZERO, and we need to shadow that value.
2385024598e40c84666cc311a42c256bbf880db3ac99sewardj         Hence apply nonptr_or_unknown to it here, after the
2386024598e40c84666cc311a42c256bbf880db3ac99sewardj         syscall completes. */
2387024598e40c84666cc311a42c256bbf880db3ac99sewardj      post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO,
2388024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             PC_SZB_FS_ZERO );
2389024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)(
2390024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, /* retval */ (UWord)NONPTR, 0,
2391024598e40c84666cc311a42c256bbf880db3ac99sewardj              /* error */  (UWord)NONPTR, 0
2392024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
2393024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2394024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2395024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2396024598e40c84666cc311a42c256bbf880db3ac99sewardj
2397024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_brk)
2398024598e40c84666cc311a42c256bbf880db3ac99sewardj   // With brk(), result (of kernel syscall, not glibc wrapper) is a heap
2399024598e40c84666cc311a42c256bbf880db3ac99sewardj   // pointer.  Make the shadow UNKNOWN.
2400024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno ==  __NR_brk) {
2401024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)(
2402024598e40c84666cc311a42c256bbf880db3ac99sewardj         tid, /* retval */ (UWord)UNKNOWN, 0,
2403024598e40c84666cc311a42c256bbf880db3ac99sewardj              /* error */  (UWord)NONPTR,  0
2404024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
2405024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2406024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2407024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2408024598e40c84666cc311a42c256bbf880db3ac99sewardj
2409024598e40c84666cc311a42c256bbf880db3ac99sewardj   // With mmap, new_mem_mmap() has already been called and added the
2410024598e40c84666cc311a42c256bbf880db3ac99sewardj   // segment (we did it there because we had the result address and size
2411024598e40c84666cc311a42c256bbf880db3ac99sewardj   // handy).  So just set the return value shadow.
2412024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_mmap
2413024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_mmap2)
2414024598e40c84666cc311a42c256bbf880db3ac99sewardj       || sysno == __NR_mmap2
2415024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2416024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_AIX5___loadx)
2417024598e40c84666cc311a42c256bbf880db3ac99sewardj       || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN)
2418024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2419024598e40c84666cc311a42c256bbf880db3ac99sewardj#      if defined(__NR_AIX5_kload)
2420024598e40c84666cc311a42c256bbf880db3ac99sewardj       || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN)
2421024598e40c84666cc311a42c256bbf880db3ac99sewardj#      endif
2422024598e40c84666cc311a42c256bbf880db3ac99sewardj      ) {
2423024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (res.isError) {
2424024598e40c84666cc311a42c256bbf880db3ac99sewardj         // mmap() had an error, return value is a small negative integer
2425024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2426024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2427024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ mmap res -> NONPTR\n");
2428024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2429024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2430024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2431024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ mmap res -> UNKNOWN\n");
2432024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2433024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2434024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2435024598e40c84666cc311a42c256bbf880db3ac99sewardj
2436024598e40c84666cc311a42c256bbf880db3ac99sewardj   // shmat uses the same scheme.  We will just have had a
2437024598e40c84666cc311a42c256bbf880db3ac99sewardj   // notification via new_mem_mmap.  Just set the return value shadow.
2438024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_shmat)
2439024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_shmat) {
2440024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (res.isError) {
2441024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2442024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2443024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ shmat res -> NONPTR\n");
2444024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2445024598e40c84666cc311a42c256bbf880db3ac99sewardj         VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2446024598e40c84666cc311a42c256bbf880db3ac99sewardj                                               /*err*/ (UWord)NONPTR, 0 );
2447024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) VG_(printf)("ZZZZZZZ shmat res -> UNKNOWN\n");
2448024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2449024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2450024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2451024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2452024598e40c84666cc311a42c256bbf880db3ac99sewardj
2453024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(__NR_shmget)
2454024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (sysno == __NR_shmget) {
2455024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: is this correct?
2456024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2457024598e40c84666cc311a42c256bbf880db3ac99sewardj                                            /*err*/ (UWord)NONPTR, 0 );
2458024598e40c84666cc311a42c256bbf880db3ac99sewardj      return;
2459024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2460024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2461024598e40c84666cc311a42c256bbf880db3ac99sewardj
2462024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* If we get here, it implies the corresponding entry in
2463024598e40c84666cc311a42c256bbf880db3ac99sewardj      post_syscall_table has .w2 == 1, which in turn implies there
2464024598e40c84666cc311a42c256bbf880db3ac99sewardj      should be special-case code for it above. */
2465024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
2466024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2467024598e40c84666cc311a42c256bbf880db3ac99sewardj
2468024598e40c84666cc311a42c256bbf880db3ac99sewardj
2469024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2470024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Functions called from generated code                         ---*/
2471024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
2472024598e40c84666cc311a42c256bbf880db3ac99sewardj
2473024598e40c84666cc311a42c256bbf880db3ac99sewardj#if SC_SEGS
2474024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void checkSeg ( Seg vseg ) {
2475024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM
2476024598e40c84666cc311a42c256bbf880db3ac99sewardj             || Seg__plausible(vseg) );
2477024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2478024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
2479024598e40c84666cc311a42c256bbf880db3ac99sewardj
2480024598e40c84666cc311a42c256bbf880db3ac99sewardj// XXX: could be more sophisticated -- actually track the lowest/highest
2481024598e40c84666cc311a42c256bbf880db3ac99sewardj// valid address used by the program, and then return False for anything
2482024598e40c84666cc311a42c256bbf880db3ac99sewardj// below that (using a suitable safety margin).  Also, nothing above
2483024598e40c84666cc311a42c256bbf880db3ac99sewardj// 0xc0000000 is valid [unless you've changed that in your kernel]
2484024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool looks_like_a_pointer(Addr a)
2485024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2486024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if defined(VGA_x86) || defined(VGA_ppc32)
2487024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4);
2488024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (a > 0x01000000UL && a < 0xFF000000UL);
2489024598e40c84666cc311a42c256bbf880db3ac99sewardj#  elif defined(VGA_amd64) || defined(VGA_ppc64)
2490024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8);
2491024598e40c84666cc311a42c256bbf880db3ac99sewardj   return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL);
2492024598e40c84666cc311a42c256bbf880db3ac99sewardj#  else
2493024598e40c84666cc311a42c256bbf880db3ac99sewardj#    error "Unsupported architecture"
2494024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2495024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2496024598e40c84666cc311a42c256bbf880db3ac99sewardj
2497024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline VG_REGPARM(1)
2498024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* nonptr_or_unknown(UWord x)
2499024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2500024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR;
2501024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n",
2502024598e40c84666cc311a42c256bbf880db3ac99sewardj                      res==UNKNOWN ? "UUU" : "nnn", x);
2503024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
2504024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2505024598e40c84666cc311a42c256bbf880db3ac99sewardj
2506024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static __attribute__((regparm(1)))
2507024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz void print_BB_entry(UInt bb)
2508024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
2509024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    VG_(printf)("%u =\n", bb);
2510024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
2511024598e40c84666cc311a42c256bbf880db3ac99sewardj
2512024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__tot_mem_refs  = 0;
2513024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__refs_in_a_seg = 0;
2514024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic ULong stats__refs_lost_seg = 0;
2515024598e40c84666cc311a42c256bbf880db3ac99sewardj
2516024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
2517024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct { ExeContext* ec; UWord count; }
2518024598e40c84666cc311a42c256bbf880db3ac99sewardj   Lossage;
2519024598e40c84666cc311a42c256bbf880db3ac99sewardj
2520024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic OSet* lossage = NULL;
2521024598e40c84666cc311a42c256bbf880db3ac99sewardj
2522024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void inc_lossage ( ExeContext* ec )
2523024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2524024598e40c84666cc311a42c256bbf880db3ac99sewardj   Lossage key, *res, *nyu;
2525024598e40c84666cc311a42c256bbf880db3ac99sewardj   key.ec = ec;
2526024598e40c84666cc311a42c256bbf880db3ac99sewardj   key.count = 0; /* frivolous */
2527024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = VG_(OSetGen_Lookup)(lossage, &key);
2528024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (res) {
2529024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(res->ec == ec);
2530024598e40c84666cc311a42c256bbf880db3ac99sewardj      res->count++;
2531024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2532024598e40c84666cc311a42c256bbf880db3ac99sewardj      nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage));
2533024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(nyu);
2534024598e40c84666cc311a42c256bbf880db3ac99sewardj      nyu->ec = ec;
2535024598e40c84666cc311a42c256bbf880db3ac99sewardj      nyu->count = 1;
2536024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(OSetGen_Insert)( lossage, nyu );
2537024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2538024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2539024598e40c84666cc311a42c256bbf880db3ac99sewardj
2540024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_lossage ( void )
2541024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2542024598e40c84666cc311a42c256bbf880db3ac99sewardj   lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec),
2543024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  /*fastCmp*/NULL,
2544024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  VG_(malloc), "pc.h_main.il.1",
2545024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  VG_(free) );
2546024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(lossage);
2547024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2548024598e40c84666cc311a42c256bbf880db3ac99sewardj
2549024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void show_lossage ( void )
2550024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2551024598e40c84666cc311a42c256bbf880db3ac99sewardj   Lossage* elem;
2552024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_(OSetGen_ResetIter)( lossage );
2553024598e40c84666cc311a42c256bbf880db3ac99sewardj   while ( (elem = VG_(OSetGen_Next)(lossage)) ) {
2554024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (elem->count < 10) continue;
2555024598e40c84666cc311a42c256bbf880db3ac99sewardj      //Char buf[100];
2556024598e40c84666cc311a42c256bbf880db3ac99sewardj      //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1);
2557024598e40c84666cc311a42c256bbf880db3ac99sewardj      //buf[sizeof(buf)-1] = 0;
2558024598e40c84666cc311a42c256bbf880db3ac99sewardj      //VG_(printf)("  %,8lu  %s\n", elem->count, buf);
2559024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count);
2560024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(pp_ExeContext)(elem->ec);
2561024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2562024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2563024598e40c84666cc311a42c256bbf880db3ac99sewardj
2564024598e40c84666cc311a42c256bbf880db3ac99sewardj// This function is called *a lot*; inlining it sped up Konqueror by 20%.
2565024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
2566024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg)
2567024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2568024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (h_clo_lossage_check) {
2569024598e40c84666cc311a42c256bbf880db3ac99sewardj     tl_assert(0);
2570024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
2571024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* seg;
2572024598e40c84666cc311a42c256bbf880db3ac99sewardj      stats__tot_mem_refs++;
2573024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (ISList__findI0( seglist, (Addr)m, &seg )) {
2574024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* m falls inside 'seg' (that is, we are making a memory
2575024598e40c84666cc311a42c256bbf880db3ac99sewardj            reference inside 'seg').  Now, really mptr_vseg should be
2576024598e40c84666cc311a42c256bbf880db3ac99sewardj            a tracked segment of some description.  Badness is when
2577024598e40c84666cc311a42c256bbf880db3ac99sewardj            mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point,
2578024598e40c84666cc311a42c256bbf880db3ac99sewardj            since that means we've lost the type of it somehow: it
2579024598e40c84666cc311a42c256bbf880db3ac99sewardj            shoud say that m points into a real segment (preferable
2580024598e40c84666cc311a42c256bbf880db3ac99sewardj            'seg'), but it doesn't. */
2581024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (Seg__status_is_SegHeap(seg)) {
2582024598e40c84666cc311a42c256bbf880db3ac99sewardj            stats__refs_in_a_seg++;
2583024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (UNKNOWN == mptr_vseg
2584024598e40c84666cc311a42c256bbf880db3ac99sewardj                || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
2585024598e40c84666cc311a42c256bbf880db3ac99sewardj               ExeContext* ec;
2586024598e40c84666cc311a42c256bbf880db3ac99sewardj               Char buf[100];
2587024598e40c84666cc311a42c256bbf880db3ac99sewardj               static UWord xx = 0;
2588024598e40c84666cc311a42c256bbf880db3ac99sewardj               stats__refs_lost_seg++;
2589024598e40c84666cc311a42c256bbf880db3ac99sewardj               ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
2590024598e40c84666cc311a42c256bbf880db3ac99sewardj               inc_lossage(ec);
2591024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (0) {
2592024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(message)(Vg_DebugMsg, "");
2593024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(message)(Vg_DebugMsg,
2594024598e40c84666cc311a42c256bbf880db3ac99sewardj                               "Lossage %s %#lx sz %lu inside block alloc'd",
2595024598e40c84666cc311a42c256bbf880db3ac99sewardj                               is_write ? "wr" : "rd", m, (UWord)sz);
2596024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(pp_ExeContext)(Seg__where(seg));
2597024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
2598024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (xx++ < 0) {
2599024598e40c84666cc311a42c256bbf880db3ac99sewardj                  Addr ip = VG_(get_IP)( VG_(get_running_tid)() );
2600024598e40c84666cc311a42c256bbf880db3ac99sewardj                  (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1);
2601024598e40c84666cc311a42c256bbf880db3ac99sewardj                  buf[sizeof(buf)-1] = 0;
2602024598e40c84666cc311a42c256bbf880db3ac99sewardj                  VG_(printf)("lossage at %p %s\n", ec, buf );
2603024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
2604024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
2605024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
2606024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2607024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
2608024598e40c84666cc311a42c256bbf880db3ac99sewardj   } /* clo_lossage_check */
2609024598e40c84666cc311a42c256bbf880db3ac99sewardj
2610024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2611024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2612024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2613024598e40c84666cc311a42c256bbf880db3ac99sewardj
2614024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (UNKNOWN == mptr_vseg) {
2615024598e40c84666cc311a42c256bbf880db3ac99sewardj      // do nothing
2616024598e40c84666cc311a42c256bbf880db3ac99sewardj
2617024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (BOTTOM == mptr_vseg) {
2618024598e40c84666cc311a42c256bbf880db3ac99sewardj      // do nothing
2619024598e40c84666cc311a42c256bbf880db3ac99sewardj
2620024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (NONPTR == mptr_vseg) {
2621024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_heap_error( m, sz, mptr_vseg, is_write );
2622024598e40c84666cc311a42c256bbf880db3ac99sewardj
2623024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2624024598e40c84666cc311a42c256bbf880db3ac99sewardj      // check all segment ranges in the circle
2625024598e40c84666cc311a42c256bbf880db3ac99sewardj      // if none match, warn about 1st seg
2626024598e40c84666cc311a42c256bbf880db3ac99sewardj      // else,          check matching one isn't freed
2627024598e40c84666cc311a42c256bbf880db3ac99sewardj      Bool is_ok = False;
2628024598e40c84666cc311a42c256bbf880db3ac99sewardj      Seg* curr  = mptr_vseg;
2629024598e40c84666cc311a42c256bbf880db3ac99sewardj      Addr mhi;
2630024598e40c84666cc311a42c256bbf880db3ac99sewardj
2631024598e40c84666cc311a42c256bbf880db3ac99sewardj      // Accesses partly outside range are an error, unless it's an aligned
2632024598e40c84666cc311a42c256bbf880db3ac99sewardj      // word-sized read, and --partial-loads-ok=yes.  This is to cope with
2633024598e40c84666cc311a42c256bbf880db3ac99sewardj      // gcc's/glibc's habits of doing word-sized accesses that read past
2634024598e40c84666cc311a42c256bbf880db3ac99sewardj      // the ends of arrays/strings.
2635024598e40c84666cc311a42c256bbf880db3ac99sewardj      // JRS 2008-sept-11: couldn't this be moved off the critical path?
2636024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (!is_write && sz == sizeof(UWord)
2637024598e40c84666cc311a42c256bbf880db3ac99sewardj          && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
2638024598e40c84666cc311a42c256bbf880db3ac99sewardj         mhi = m;
2639024598e40c84666cc311a42c256bbf880db3ac99sewardj      } else {
2640024598e40c84666cc311a42c256bbf880db3ac99sewardj         mhi = m+sz-1;
2641024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
2642024598e40c84666cc311a42c256bbf880db3ac99sewardj
2643024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi);
2644024598e40c84666cc311a42c256bbf880db3ac99sewardj      is_ok = curr->addr <= m && mhi < curr->addr + curr->szB;
2645024598e40c84666cc311a42c256bbf880db3ac99sewardj
2646024598e40c84666cc311a42c256bbf880db3ac99sewardj      // If it's an overrun/underrun of a freed block, don't give both
2647024598e40c84666cc311a42c256bbf880db3ac99sewardj      // warnings, since the first one mentions that the block has been
2648024598e40c84666cc311a42c256bbf880db3ac99sewardj      // freed.
2649024598e40c84666cc311a42c256bbf880db3ac99sewardj      if ( ! is_ok || Seg__is_freed(curr) )
2650024598e40c84666cc311a42c256bbf880db3ac99sewardj         h_record_heap_error( m, sz, mptr_vseg, is_write );
2651024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2652024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2653024598e40c84666cc311a42c256bbf880db3ac99sewardj
2654024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Load handlers ------------------ //
2655024598e40c84666cc311a42c256bbf880db3ac99sewardj
2656024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use:
2657024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load1 check_load2 check_load4_P
2658024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load4  (for 32-bit FP reads)
2659024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load8  (for 64-bit FP reads)
2660024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load16 (for xmm/altivec reads)
2661024598e40c84666cc311a42c256bbf880db3ac99sewardj   On 64 bit targets, we will use:
2662024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load1 check_load2 check_load4 check_load8_P
2663024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load8  (for 64-bit FP reads)
2664024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_load16 (for xmm/altivec reads)
2665024598e40c84666cc311a42c256bbf880db3ac99sewardj
2666024598e40c84666cc311a42c256bbf880db3ac99sewardj   A "_P" handler reads a pointer from memory, and so returns a value
2667024598e40c84666cc311a42c256bbf880db3ac99sewardj   to the generated code -- the pointer's shadow value.  That implies
2668024598e40c84666cc311a42c256bbf880db3ac99sewardj   that check_load4_P is only to be called on a 32 bit host and
2669024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load8_P is only to be called on a 64 bit host.  For all other
2670024598e40c84666cc311a42c256bbf880db3ac99sewardj   cases no shadow value is returned; we merely check that the pointer
2671024598e40c84666cc311a42c256bbf880db3ac99sewardj   (m) matches the block described by its shadow value (mptr_vseg).
2672024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
2673024598e40c84666cc311a42c256bbf880db3ac99sewardj
2674024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit loads on both 32 bit and 64 bit targets.
2675024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2676024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load16(Addr m, Seg* mptr_vseg)
2677024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2678024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2679024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2680024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2681024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 16, mptr_vseg);
2682024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2683024598e40c84666cc311a42c256bbf880db3ac99sewardj
2684024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit FP-or-otherwise-nonpointer loads on both
2685024598e40c84666cc311a42c256bbf880db3ac99sewardj// 32 bit and 64 bit targets.
2686024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2687024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load8(Addr m, Seg* mptr_vseg)
2688024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2689024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2690024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2691024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2692024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2693024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2694024598e40c84666cc311a42c256bbf880db3ac99sewardj
2695024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit loads on 64 bit targets.  It must
2696024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets.
2697024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg
2698024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2699024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load8_P(Addr m, Seg* mptr_vseg)
2700024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2701024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* vseg;
2702024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2703024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2704024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2705024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2706024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2707024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_8_ALIGNED(m)) {
2708024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = get_mem_vseg(m);
2709024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2710024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = nonptr_or_unknown( *(ULong*)m );
2711024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2712024598e40c84666cc311a42c256bbf880db3ac99sewardj   return vseg;
2713024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2714024598e40c84666cc311a42c256bbf880db3ac99sewardj
2715024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit loads on 32 bit targets.  It must
2716024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets.
2717024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg
2718024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2719024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load4_P(Addr m, Seg* mptr_vseg)
2720024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2721024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* vseg;
2722024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2723024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2724024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2725024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2726024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2727024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_4_ALIGNED(m)) {
2728024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = get_mem_vseg(m);
2729024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2730024598e40c84666cc311a42c256bbf880db3ac99sewardj      vseg = nonptr_or_unknown( *(UInt*)m );
2731024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2732024598e40c84666cc311a42c256bbf880db3ac99sewardj   return vseg;
2733024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2734024598e40c84666cc311a42c256bbf880db3ac99sewardj
2735024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2736024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2737024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load4(Addr m, Seg* mptr_vseg)
2738024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2739024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2740024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2741024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2742024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2743024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2744024598e40c84666cc311a42c256bbf880db3ac99sewardj
2745024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2746024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2747024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load2(Addr m, Seg* mptr_vseg)
2748024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2749024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2750024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2751024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2752024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 2, mptr_vseg);
2753024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2754024598e40c84666cc311a42c256bbf880db3ac99sewardj
2755024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2756024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2757024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load1(Addr m, Seg* mptr_vseg)
2758024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2759024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2760024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2761024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2762024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/False, m, 1, mptr_vseg);
2763024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2764024598e40c84666cc311a42c256bbf880db3ac99sewardj
2765024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Store handlers ------------------ //
2766024598e40c84666cc311a42c256bbf880db3ac99sewardj
2767024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use:
2768024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store1 check_store2 check_store4_P
2769024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store4 (for 32-bit nonpointer stores)
2770024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store8_ms4B_ls4B (for 64-bit stores)
2771024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores)
2772024598e40c84666cc311a42c256bbf880db3ac99sewardj
2773024598e40c84666cc311a42c256bbf880db3ac99sewardj   On 64 bit targets, we will use:
2774024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store1 check_store2 check_store4 check_store8_P
2775024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store8_all8B (for 64-bit nonpointer stores)
2776024598e40c84666cc311a42c256bbf880db3ac99sewardj      check_store16_ms8B_ls8B (for xmm/altivec stores)
2777024598e40c84666cc311a42c256bbf880db3ac99sewardj
2778024598e40c84666cc311a42c256bbf880db3ac99sewardj   A "_P" handler writes a pointer to memory, and so has an extra
2779024598e40c84666cc311a42c256bbf880db3ac99sewardj   argument -- the pointer's shadow value.  That implies that
2780024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_store4_P is only to be called on a 32 bit host and
2781024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_store8_P is only to be called on a 64 bit host.  For all
2782024598e40c84666cc311a42c256bbf880db3ac99sewardj   other cases, and for the misaligned _P cases, the strategy is to
2783024598e40c84666cc311a42c256bbf880db3ac99sewardj   let the store go through, and then snoop around with
2784024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown to fix up the shadow values of any affected
2785024598e40c84666cc311a42c256bbf880db3ac99sewardj   words. */
2786024598e40c84666cc311a42c256bbf880db3ac99sewardj
2787024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Apply nonptr_or_unknown to all the words intersecting
2788024598e40c84666cc311a42c256bbf880db3ac99sewardj   [a, a+len). */
2789024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2)
2790024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid nonptr_or_unknown_range ( Addr a, SizeT len )
2791024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2792024598e40c84666cc311a42c256bbf880db3ac99sewardj   const SizeT wszB = sizeof(UWord);
2793024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr wfirst = VG_ROUNDDN(a,       wszB);
2794024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr wlast  = VG_ROUNDDN(a+len-1, wszB);
2795024598e40c84666cc311a42c256bbf880db3ac99sewardj   Addr a2;
2796024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(wfirst <= wlast);
2797024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (a2 = wfirst ; a2 <= wlast; a2 += wszB) {
2798024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 ));
2799024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2800024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2801024598e40c84666cc311a42c256bbf880db3ac99sewardj
2802024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets.  The
2803024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
2804024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
2805024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2806024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg,
2807024598e40c84666cc311a42c256bbf880db3ac99sewardj                             UWord ms8B, UWord ls8B)
2808024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2809024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2810024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2811024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2812024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2813024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2814024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2815024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
2816024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
2817024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
2818024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 0) = ls8B;
2819024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 8) = ms8B;
2820024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2821024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 0) = ms8B;
2822024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(ULong*)(m + 8) = ls8B;
2823024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2824024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 16);
2825024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2826024598e40c84666cc311a42c256bbf880db3ac99sewardj
2827024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets.  The
2828024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
2829024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
2830024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2831024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg,
2832024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   UWord ms4B, UWord w2,
2833024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   UWord w1,   UWord ls4B)
2834024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2835024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2836024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2837024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2838024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2839024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2840024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2841024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
2842024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
2843024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
2844024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  0) = ls4B;
2845024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  4) = w1;
2846024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  8) = w2;
2847024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 12) = ms4B;
2848024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2849024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  0) = ms4B;
2850024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  4) = w2;
2851024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m +  8) = w1;
2852024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 12) = ls4B;
2853024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2854024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 16);
2855024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2856024598e40c84666cc311a42c256bbf880db3ac99sewardj
2857024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 32 bit targets.  The
2858024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant
2859024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first.
2860024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2861024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg,
2862024598e40c84666cc311a42c256bbf880db3ac99sewardj                            UWord ms4B, UWord ls4B)
2863024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2864024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2865024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2866024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2867024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2868024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
2869024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2870024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (host_is_little_endian()) {
2871024598e40c84666cc311a42c256bbf880db3ac99sewardj      // FIXME: aren't we really concerned whether the guest
2872024598e40c84666cc311a42c256bbf880db3ac99sewardj      // is little endian, not whether the host is?
2873024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 0) = ls4B;
2874024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 4) = ms4B;
2875024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2876024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 0) = ms4B;
2877024598e40c84666cc311a42c256bbf880db3ac99sewardj      *(UInt*)(m + 4) = ls4B;
2878024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2879024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 8);
2880024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2881024598e40c84666cc311a42c256bbf880db3ac99sewardj
2882024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit non pointer stores on 64 bit targets.
2883024598e40c84666cc311a42c256bbf880db3ac99sewardj// It must not be called on 32 bit targets.
2884024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2885024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B)
2886024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2887024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2888024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2889024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2890024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2891024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
2892024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2893024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(ULong*)m = all8B;
2894024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 8);
2895024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2896024598e40c84666cc311a42c256bbf880db3ac99sewardj
2897024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 64 bit targets.  It must
2898024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets.
2899024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2900024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
2901024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2902024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2903024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2904024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(t_vseg);
2905024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2906024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2907024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
2908024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2909024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(ULong*)m = t;
2910024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_8_ALIGNED(m)) {
2911024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( m, t_vseg );
2912024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2913024598e40c84666cc311a42c256bbf880db3ac99sewardj      // straddling two words
2914024598e40c84666cc311a42c256bbf880db3ac99sewardj      nonptr_or_unknown_range(m, 8);
2915024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2916024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2917024598e40c84666cc311a42c256bbf880db3ac99sewardj
2918024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit stores on 32 bit targets.  It must
2919024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets.
2920024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2921024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
2922024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2923024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2924024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2925024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(t_vseg);
2926024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2927024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2928024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
2929024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here
2930024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UInt*)m = t;
2931024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_IS_4_ALIGNED(m)) {
2932024598e40c84666cc311a42c256bbf880db3ac99sewardj      set_mem_vseg( m, t_vseg );
2933024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
2934024598e40c84666cc311a42c256bbf880db3ac99sewardj      // straddling two words
2935024598e40c84666cc311a42c256bbf880db3ac99sewardj      nonptr_or_unknown_range(m, 4);
2936024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2937024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2938024598e40c84666cc311a42c256bbf880db3ac99sewardj
2939024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2940024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2941024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4(Addr m, Seg* mptr_vseg, UWord t)
2942024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2943024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2944024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2945024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2946024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
2947024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 4-byte type!)
2948024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UInt*)m = t;
2949024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 4);
2950024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2951024598e40c84666cc311a42c256bbf880db3ac99sewardj
2952024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2953024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2954024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store2(Addr m, Seg* mptr_vseg, UWord t)
2955024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2956024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2957024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2958024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2959024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 2, mptr_vseg);
2960024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 2-byte type!)
2961024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UShort*)m = t;
2962024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 2);
2963024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2964024598e40c84666cc311a42c256bbf880db3ac99sewardj
2965024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets.
2966024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3)
2967024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store1(Addr m, Seg* mptr_vseg, UWord t)
2968024598e40c84666cc311a42c256bbf880db3ac99sewardj{
2969024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
2970024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(mptr_vseg);
2971024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
2972024598e40c84666cc311a42c256bbf880db3ac99sewardj   check_load_or_store(/*is_write*/True, m, 1, mptr_vseg);
2973024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Actually *do* the STORE here  (Nb: cast must be to 1-byte type!)
2974024598e40c84666cc311a42c256bbf880db3ac99sewardj   *(UChar*)m = t;
2975024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown_range(m, 1);
2976024598e40c84666cc311a42c256bbf880db3ac99sewardj}
2977024598e40c84666cc311a42c256bbf880db3ac99sewardj
2978024598e40c84666cc311a42c256bbf880db3ac99sewardj
2979024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM
2980024598e40c84666cc311a42c256bbf880db3ac99sewardj//     be changed to NONPTR by a range check on the result.
2981024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \
2982024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (BOTTOM == seg1 || BOTTOM == seg2) { bt;                   \
2983024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (NONPTR == seg1)  { if      (NONPTR == seg2)  { nn; }  \
2984024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { nu; }    \
2985024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { np; }    \
2986024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else if (UNKNOWN == seg1) { if      (NONPTR == seg2)  { un; }    \
2987024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { uu; }    \
2988024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { up; }    \
2989024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else                      { if      (NONPTR == seg2)  { pn; }    \
2990024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else if (UNKNOWN == seg2) { pu; }    \
2991024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 else                      { pp; }    \
2992024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
2993024598e40c84666cc311a42c256bbf880db3ac99sewardj
2994024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINERROR(opname)                    \
2995024598e40c84666cc311a42c256bbf880db3ac99sewardj   h_record_arith_error(seg1, seg2, opname);  \
2996024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = NONPTR
2997024598e40c84666cc311a42c256bbf880db3ac99sewardj
2998024598e40c84666cc311a42c256bbf880db3ac99sewardj
2999024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3000024598e40c84666cc311a42c256bbf880db3ac99sewardj//  + | n  ?  p
3001024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3002024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3003024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3004024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  e   (all results become n if they look like a non-pointer)
3005024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3006024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname)
3007024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3008024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3009024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3010024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3011024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3012024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3013024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3014024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3015024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN, out = seg2,
3016024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3017024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = UNKNOWN,       BINERROR(opname)
3018024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3019024598e40c84666cc311a42c256bbf880db3ac99sewardj   return ( looks_like_a_pointer(result) ? out : NONPTR );
3020024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3021024598e40c84666cc311a42c256bbf880db3ac99sewardj
3022024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result)
3023024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3024024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3025024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3026024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3027024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3028024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3029024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = do_addW_result(seg1, seg2, result, "Add32/Add64");
3030024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3031024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(out);
3032024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3033024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3034024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3035024598e40c84666cc311a42c256bbf880db3ac99sewardj
3036024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3037024598e40c84666cc311a42c256bbf880db3ac99sewardj//  - | n  ?  p      (Nb: operation is seg1 - seg2)
3038024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3039024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  n+     (+) happens a lot due to "cmp", but result should never
3040024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  n/B        be used, so give 'n'
3041024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  p? n*/B   (*) and possibly link the segments
3042024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3043024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result)
3044024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3045024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3046024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3047024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3048024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3049024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3050024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Nb: when returning BOTTOM, don't let it go through the range-check;
3051024598e40c84666cc311a42c256bbf880db3ac99sewardj   //     a segment linking offset can easily look like a nonptr.
3052024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3053024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3054024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN,    out = NONPTR,
3055024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN,    return BOTTOM,
3056024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = seg1/*??*/, return BOTTOM
3057024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3058024598e40c84666cc311a42c256bbf880db3ac99sewardj   #if 0
3059024598e40c84666cc311a42c256bbf880db3ac99sewardj         // This is for the p-p segment-linking case
3060024598e40c84666cc311a42c256bbf880db3ac99sewardj         Seg end2 = seg2;
3061024598e40c84666cc311a42c256bbf880db3ac99sewardj         while (end2->links != seg2) end2 = end2->links;
3062024598e40c84666cc311a42c256bbf880db3ac99sewardj         end2->links = seg1->links;
3063024598e40c84666cc311a42c256bbf880db3ac99sewardj         seg1->links = seg2;
3064024598e40c84666cc311a42c256bbf880db3ac99sewardj         return NONPTR;
3065024598e40c84666cc311a42c256bbf880db3ac99sewardj   #endif
3066024598e40c84666cc311a42c256bbf880db3ac99sewardj   return ( looks_like_a_pointer(result) ? out : NONPTR );
3067024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3068024598e40c84666cc311a42c256bbf880db3ac99sewardj
3069024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3070024598e40c84666cc311a42c256bbf880db3ac99sewardj//  & | n  ?  p
3071024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3072024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3073024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3074024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  *  (*) if p1==p2 then p else e (see comment)
3075024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3076024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Seems to be OK to And two pointers:
3077024598e40c84666cc311a42c256bbf880db3ac99sewardj     testq %ptr1,%ptr2
3078024598e40c84666cc311a42c256bbf880db3ac99sewardj     jnz ..
3079024598e40c84666cc311a42c256bbf880db3ac99sewardj   which possibly derives from
3080024598e40c84666cc311a42c256bbf880db3ac99sewardj     if (ptr1 & ptr2) { A } else { B }
3081024598e40c84666cc311a42c256bbf880db3ac99sewardj   not sure what that means
3082024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3083024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2,
3084024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  UWord result, UWord args_diff)
3085024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3086024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3087024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (0 == args_diff) {
3088024598e40c84666cc311a42c256bbf880db3ac99sewardj      // p1==p2
3089024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1;
3090024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3091024598e40c84666cc311a42c256bbf880db3ac99sewardj      BINOP(
3092024598e40c84666cc311a42c256bbf880db3ac99sewardj         return BOTTOM,
3093024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = NONPTR,  out = UNKNOWN, out = seg2,
3094024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3095024598e40c84666cc311a42c256bbf880db3ac99sewardj         out = seg1,    out = UNKNOWN, out = NONPTR
3096024598e40c84666cc311a42c256bbf880db3ac99sewardj                                       /*BINERROR("And32/And64")*/
3097024598e40c84666cc311a42c256bbf880db3ac99sewardj      );
3098024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3099024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = ( looks_like_a_pointer(result) ? out : NONPTR );
3100024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3101024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3102024598e40c84666cc311a42c256bbf880db3ac99sewardj
3103024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3104024598e40c84666cc311a42c256bbf880db3ac99sewardj// `|`| n  ?  p
3105024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3106024598e40c84666cc311a42c256bbf880db3ac99sewardj//  n | n  ?  p
3107024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ? | ?  ?  ?
3108024598e40c84666cc311a42c256bbf880db3ac99sewardj//  p | p  ?  n
3109024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3110024598e40c84666cc311a42c256bbf880db3ac99sewardj/* It's OK to Or two pointers together, but the result definitely
3111024598e40c84666cc311a42c256bbf880db3ac99sewardj   isn't a pointer.  Why would you want to do that?  Because of this:
3112024598e40c84666cc311a42c256bbf880db3ac99sewardj     char* p1 = malloc(..);
3113024598e40c84666cc311a42c256bbf880db3ac99sewardj     char* p2 = malloc(..);
3114024598e40c84666cc311a42c256bbf880db3ac99sewardj     ...
3115024598e40c84666cc311a42c256bbf880db3ac99sewardj     if (p1 || p2) { .. }
3116024598e40c84666cc311a42c256bbf880db3ac99sewardj   In this case gcc on x86/amd64 quite literally or-s the two pointers
3117024598e40c84666cc311a42c256bbf880db3ac99sewardj   together and throws away the result, the purpose of which is merely
3118024598e40c84666cc311a42c256bbf880db3ac99sewardj   to sets %eflags.Z/%rflags.Z.  So we have to allow it.
3119024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3120024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result)
3121024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3122024598e40c84666cc311a42c256bbf880db3ac99sewardj   Seg* out;
3123024598e40c84666cc311a42c256bbf880db3ac99sewardj   BINOP(
3124024598e40c84666cc311a42c256bbf880db3ac99sewardj      return BOTTOM,
3125024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = NONPTR,  out = UNKNOWN, out = seg2,
3126024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3127024598e40c84666cc311a42c256bbf880db3ac99sewardj      out = seg1,    out = UNKNOWN, out = NONPTR
3128024598e40c84666cc311a42c256bbf880db3ac99sewardj   );
3129024598e40c84666cc311a42c256bbf880db3ac99sewardj   out = ( looks_like_a_pointer(result) ? out : NONPTR );
3130024598e40c84666cc311a42c256bbf880db3ac99sewardj   return out;
3131024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3132024598e40c84666cc311a42c256bbf880db3ac99sewardj
3133024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3134024598e40c84666cc311a42c256bbf880db3ac99sewardj//  ~ | n  ?  p
3135024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3136024598e40c84666cc311a42c256bbf880db3ac99sewardj//    | n  n  n
3137024598e40c84666cc311a42c256bbf880db3ac99sewardj// -------------
3138024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result)
3139024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3140024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3141024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3142024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3143024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (BOTTOM == seg1) return BOTTOM;
3144024598e40c84666cc311a42c256bbf880db3ac99sewardj   return NONPTR;
3145024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3146024598e40c84666cc311a42c256bbf880db3ac99sewardj
3147024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pointers are rarely multiplied, but sometimes legitimately, eg. as hash
3148024598e40c84666cc311a42c256bbf880db3ac99sewardj// function inputs.  But two pointers args --> error.
3149024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pretend it always returns a nonptr.  Maybe improve later.
3150024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2)
3151024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3152024598e40c84666cc311a42c256bbf880db3ac99sewardj#  if SC_SEGS
3153024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg1);
3154024598e40c84666cc311a42c256bbf880db3ac99sewardj   checkSeg(seg2);
3155024598e40c84666cc311a42c256bbf880db3ac99sewardj#  endif
3156024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (is_known_segment(seg1) && is_known_segment(seg2))
3157024598e40c84666cc311a42c256bbf880db3ac99sewardj      h_record_arith_error(seg1, seg2, "Mul32/Mul64");
3158024598e40c84666cc311a42c256bbf880db3ac99sewardj   return NONPTR;
3159024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3160024598e40c84666cc311a42c256bbf880db3ac99sewardj
3161024598e40c84666cc311a42c256bbf880db3ac99sewardj
3162024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3163024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Instrumentation                                              ---*/
3164024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3165024598e40c84666cc311a42c256bbf880db3ac99sewardj
3166024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The h_ instrumenter that follows is complex, since it deals with
3167024598e40c84666cc311a42c256bbf880db3ac99sewardj   shadow value computation.
3168024598e40c84666cc311a42c256bbf880db3ac99sewardj
3169024598e40c84666cc311a42c256bbf880db3ac99sewardj   It also needs to generate instrumentation for the sg_ side of
3170024598e40c84666cc311a42c256bbf880db3ac99sewardj   things.  That's relatively straightforward.  However, rather than
3171024598e40c84666cc311a42c256bbf880db3ac99sewardj   confuse the code herein any further, we simply delegate the problem
3172024598e40c84666cc311a42c256bbf880db3ac99sewardj   to sg_main.c, by using the four functions
3173024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_{init,fini,IRStmt,final_jump}.  These four completely
3174024598e40c84666cc311a42c256bbf880db3ac99sewardj   abstractify the sg_ instrumentation.  See comments in sg_main.c's
3175024598e40c84666cc311a42c256bbf880db3ac99sewardj   instrumentation section for further details. */
3176024598e40c84666cc311a42c256bbf880db3ac99sewardj
3177024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Carries around state during Ptrcheck instrumentation. */
3178024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef
3179024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct {
3180024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* MODIFIED: the superblock being constructed.  IRStmts are
3181024598e40c84666cc311a42c256bbf880db3ac99sewardj         added. */
3182024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRSB* bb;
3183024598e40c84666cc311a42c256bbf880db3ac99sewardj      Bool  trace;
3184024598e40c84666cc311a42c256bbf880db3ac99sewardj
3185024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
3186024598e40c84666cc311a42c256bbf880db3ac99sewardj         original temps to their current their current shadow temp.
3187024598e40c84666cc311a42c256bbf880db3ac99sewardj         Initially all entries are IRTemp_INVALID.  Entries are added
3188024598e40c84666cc311a42c256bbf880db3ac99sewardj         lazily since many original temps are not used due to
3189024598e40c84666cc311a42c256bbf880db3ac99sewardj         optimisation prior to instrumentation.  Note that only
3190024598e40c84666cc311a42c256bbf880db3ac99sewardj         integer temps of the guest word size are shadowed, since it
3191024598e40c84666cc311a42c256bbf880db3ac99sewardj         is impossible (or meaningless) to hold a pointer in any other
3192024598e40c84666cc311a42c256bbf880db3ac99sewardj         type of temp. */
3193024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRTemp* tmpMap;
3194024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int     n_originalTmps; /* for range checking */
3195024598e40c84666cc311a42c256bbf880db3ac99sewardj
3196024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the host word type.  Needed for constructing
3197024598e40c84666cc311a42c256bbf880db3ac99sewardj         arguments of type 'HWord' to be passed to helper functions.
3198024598e40c84666cc311a42c256bbf880db3ac99sewardj         Ity_I32 or Ity_I64 only. */
3199024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRType hWordTy;
3200024598e40c84666cc311a42c256bbf880db3ac99sewardj
3201024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
3202024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRType gWordTy;
3203024598e40c84666cc311a42c256bbf880db3ac99sewardj
3204024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* READONLY: the guest state size, so we can generate shadow
3205024598e40c84666cc311a42c256bbf880db3ac99sewardj         offsets correctly. */
3206024598e40c84666cc311a42c256bbf880db3ac99sewardj      Int guest_state_sizeB;
3207024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3208024598e40c84666cc311a42c256bbf880db3ac99sewardj   PCEnv;
3209024598e40c84666cc311a42c256bbf880db3ac99sewardj
3210024598e40c84666cc311a42c256bbf880db3ac99sewardj/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
3211024598e40c84666cc311a42c256bbf880db3ac99sewardj   demand), as they are encountered.  This is for two reasons.
3212024598e40c84666cc311a42c256bbf880db3ac99sewardj
3213024598e40c84666cc311a42c256bbf880db3ac99sewardj   (1) (less important reason): Many original tmps are unused due to
3214024598e40c84666cc311a42c256bbf880db3ac99sewardj   initial IR optimisation, and we do not want to spaces in tables
3215024598e40c84666cc311a42c256bbf880db3ac99sewardj   tracking them.
3216024598e40c84666cc311a42c256bbf880db3ac99sewardj
3217024598e40c84666cc311a42c256bbf880db3ac99sewardj   Shadow IRTemps are therefore allocated on demand.  pce.tmpMap is a
3218024598e40c84666cc311a42c256bbf880db3ac99sewardj   table indexed [0 .. n_types-1], which gives the current shadow for
3219024598e40c84666cc311a42c256bbf880db3ac99sewardj   each original tmp, or INVALID_IRTEMP if none is so far assigned.
3220024598e40c84666cc311a42c256bbf880db3ac99sewardj   It is necessary to support making multiple assignments to a shadow
3221024598e40c84666cc311a42c256bbf880db3ac99sewardj   -- specifically, after testing a shadow for definedness, it needs
3222024598e40c84666cc311a42c256bbf880db3ac99sewardj   to be made defined.  But IR's SSA property disallows this.
3223024598e40c84666cc311a42c256bbf880db3ac99sewardj
3224024598e40c84666cc311a42c256bbf880db3ac99sewardj   (2) (more important reason): Therefore, when a shadow needs to get
3225024598e40c84666cc311a42c256bbf880db3ac99sewardj   a new value, a new temporary is created, the value is assigned to
3226024598e40c84666cc311a42c256bbf880db3ac99sewardj   that, and the tmpMap is updated to reflect the new binding.
3227024598e40c84666cc311a42c256bbf880db3ac99sewardj
3228024598e40c84666cc311a42c256bbf880db3ac99sewardj   A corollary is that if the tmpMap maps a given tmp to
3229024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
3230024598e40c84666cc311a42c256bbf880db3ac99sewardj   there's a read-before-write error in the original tmps.  The IR
3231024598e40c84666cc311a42c256bbf880db3ac99sewardj   sanity checker should catch all such anomalies, however.
3232024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
3233024598e40c84666cc311a42c256bbf880db3ac99sewardj
3234024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Find the tmp currently shadowing the given original tmp.  If none
3235024598e40c84666cc311a42c256bbf880db3ac99sewardj   so far exists, allocate one.  */
3236024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig )
3237024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3238024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(orig < pce->n_originalTmps);
3239024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3240024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->tmpMap[orig] == IRTemp_INVALID) {
3241024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(0);
3242024598e40c84666cc311a42c256bbf880db3ac99sewardj      pce->tmpMap[orig]
3243024598e40c84666cc311a42c256bbf880db3ac99sewardj         = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3244024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3245024598e40c84666cc311a42c256bbf880db3ac99sewardj   return pce->tmpMap[orig];
3246024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3247024598e40c84666cc311a42c256bbf880db3ac99sewardj
3248024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Allocate a new shadow for the given original tmp.  This means any
3249024598e40c84666cc311a42c256bbf880db3ac99sewardj   previous shadow is abandoned.  This is needed because it is
3250024598e40c84666cc311a42c256bbf880db3ac99sewardj   necessary to give a new value to a shadow once it has been tested
3251024598e40c84666cc311a42c256bbf880db3ac99sewardj   for undefinedness, but unfortunately IR's SSA property disallows
3252024598e40c84666cc311a42c256bbf880db3ac99sewardj   this.  Instead we must abandon the old shadow, allocate a new one
3253024598e40c84666cc311a42c256bbf880db3ac99sewardj   and use that instead. */
3254024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((noinline))
3255024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig )
3256024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3257024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(orig < pce->n_originalTmps);
3258024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3259024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce->tmpMap[orig]
3260024598e40c84666cc311a42c256bbf880db3ac99sewardj      = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3261024598e40c84666cc311a42c256bbf880db3ac99sewardj   return pce->tmpMap[orig];
3262024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3263024598e40c84666cc311a42c256bbf880db3ac99sewardj
3264024598e40c84666cc311a42c256bbf880db3ac99sewardj
3265024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3266024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- IRAtoms -- a subset of IRExprs                       ---*/
3267024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3268024598e40c84666cc311a42c256bbf880db3ac99sewardj
3269024598e40c84666cc311a42c256bbf880db3ac99sewardj/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
3270024598e40c84666cc311a42c256bbf880db3ac99sewardj   isIRAtom() in libvex_ir.h.  Because this instrumenter expects flat
3271024598e40c84666cc311a42c256bbf880db3ac99sewardj   input, most of this code deals in atoms.  Usefully, a value atom
3272024598e40c84666cc311a42c256bbf880db3ac99sewardj   always has a V-value which is also an atom: constants are shadowed
3273024598e40c84666cc311a42c256bbf880db3ac99sewardj   by constants, and temps are shadowed by the corresponding shadow
3274024598e40c84666cc311a42c256bbf880db3ac99sewardj   temporary. */
3275024598e40c84666cc311a42c256bbf880db3ac99sewardj
3276024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef  IRExpr  IRAtom;
3277024598e40c84666cc311a42c256bbf880db3ac99sewardj
3278024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks
3279024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    like it's from original code? */
3280024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 )
3281024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3282024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const)
3283024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3284024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps)
3285024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3286024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3287024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3288024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
3289024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks
3290024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    like it's from shadow code? */
3291024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 )
3292024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3293024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const)
3294024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3295024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps)
3296024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3297024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3298024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3299024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz
3300024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): check that both args are atoms and
3301024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    are identically-kinded. */
3302024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
3303024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz {
3304024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
3305024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3306024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    if (a1->tag == Iex_Const && a2->tag == Iex_Const)
3307024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz       return True;
3308024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz    return False;
3309024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz }
3310024598e40c84666cc311a42c256bbf880db3ac99sewardj
3311024598e40c84666cc311a42c256bbf880db3ac99sewardj
3312024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3313024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Constructing IR fragments                            ---*/
3314024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/
3315024598e40c84666cc311a42c256bbf880db3ac99sewardj
3316024598e40c84666cc311a42c256bbf880db3ac99sewardj/* add stmt to a bb */
3317024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
3318024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->trace) {
3319024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("  %c: ", cat);
3320024598e40c84666cc311a42c256bbf880db3ac99sewardj      ppIRStmt(st);
3321024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(printf)("\n");
3322024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3323024598e40c84666cc311a42c256bbf880db3ac99sewardj   addStmtToIRSB(pce->bb, st);
3324024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3325024598e40c84666cc311a42c256bbf880db3ac99sewardj
3326024598e40c84666cc311a42c256bbf880db3ac99sewardj/* assign value to tmp */
3327024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline
3328024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) {
3329024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt(cat, pce, IRStmt_WrTmp(tmp,expr));
3330024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3331024598e40c84666cc311a42c256bbf880db3ac99sewardj
3332024598e40c84666cc311a42c256bbf880db3ac99sewardj/* build various kinds of expressions */
3333024598e40c84666cc311a42c256bbf880db3ac99sewardj#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
3334024598e40c84666cc311a42c256bbf880db3ac99sewardj#define unop(_op, _arg)          IRExpr_Unop((_op),(_arg))
3335024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU8(_n)                 IRExpr_Const(IRConst_U8(_n))
3336024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU16(_n)                IRExpr_Const(IRConst_U16(_n))
3337024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
3338024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
3339024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkV128(_n)               IRExpr_Const(IRConst_V128(_n))
3340024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkexpr(_tmp)             IRExpr_RdTmp((_tmp))
3341024598e40c84666cc311a42c256bbf880db3ac99sewardj
3342024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Bind the given expression to a new temporary, and return the
3343024598e40c84666cc311a42c256bbf880db3ac99sewardj   temporary.  This effectively converts an arbitrary expression into
3344024598e40c84666cc311a42c256bbf880db3ac99sewardj   an atom.
3345024598e40c84666cc311a42c256bbf880db3ac99sewardj
3346024598e40c84666cc311a42c256bbf880db3ac99sewardj   'ty' is the type of 'e' and hence the type that the new temporary
3347024598e40c84666cc311a42c256bbf880db3ac99sewardj   needs to be.  But passing it is redundant, since we can deduce the
3348024598e40c84666cc311a42c256bbf880db3ac99sewardj   type merely by inspecting 'e'.  So at least that fact to assert
3349024598e40c84666cc311a42c256bbf880db3ac99sewardj   that the two types agree. */
3350024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) {
3351024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp t;
3352024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRType tyE = typeOfIRExpr(pce->bb->tyenv, e);
3353024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
3354024598e40c84666cc311a42c256bbf880db3ac99sewardj   t = newIRTemp(pce->bb->tyenv, ty);
3355024598e40c84666cc311a42c256bbf880db3ac99sewardj   assign(cat, pce, t, e);
3356024598e40c84666cc311a42c256bbf880db3ac99sewardj   return mkexpr(t);
3357024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3358024598e40c84666cc311a42c256bbf880db3ac99sewardj
3359024598e40c84666cc311a42c256bbf880db3ac99sewardj
3360024598e40c84666cc311a42c256bbf880db3ac99sewardj
3361024598e40c84666cc311a42c256bbf880db3ac99sewardj//-----------------------------------------------------------------------
3362024598e40c84666cc311a42c256bbf880db3ac99sewardj// Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows.
3363024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3364024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/seg):
3365024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after modifying a word-sized value in/into a TempReg:
3366024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L
3367024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - BSWAP
3368024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3369024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/UNKNOWN):
3370024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when introducing a new word-sized value into a TempReg:
3371024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOVL l, t2
3372024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3373024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying a word-sized value which lacks a corresponding segment
3374024598e40c84666cc311a42c256bbf880db3ac99sewardj//   into a TempReg:
3375024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled LDL
3376024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3377024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when a sub-word of a word (or two) is updated:
3378024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - SHROTL
3379024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB]
3380024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - PUT[WB]
3381024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   STL (2 range checks)
3382024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   STW (2 range checks)
3383024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled STW
3384024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - STB
3385024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3386024598e40c84666cc311a42c256bbf880db3ac99sewardj// Just copy:
3387024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying word-sized values:
3388024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOVL t1, t2 (--optimise=no only)
3389024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - CMOV
3390024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GETL, PUTL
3391024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled LDL, unstraddled STL
3392024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3393024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when barely changing
3394024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - INC[LWB]/DEC[LWB]
3395024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3396024598e40c84666cc311a42c256bbf880db3ac99sewardj// Set to NONPTR:
3397024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying a sub-word value into a TempReg:
3398024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - MOV[WB] l, t2
3399024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GET[WB]
3400024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - unstraddled LDW
3401024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - straddled   LDW
3402024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - LDB
3403024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - POP[WB]
3404024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3405024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a TempReg:
3406024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - GETF
3407024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - CC2VAL
3408024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - POPL
3409024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3410024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a memory word:
3411024598e40c84666cc311a42c256bbf880db3ac99sewardj//    - FPU_W
3412024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3413024598e40c84666cc311a42c256bbf880db3ac99sewardj// Do nothing:
3414024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LOCK, INCEIP
3415024598e40c84666cc311a42c256bbf880db3ac99sewardj// - WIDEN[WB]
3416024598e40c84666cc311a42c256bbf880db3ac99sewardj// - JMP, JIFZ
3417024598e40c84666cc311a42c256bbf880db3ac99sewardj// - CALLM_[SE], PUSHL, CALLM, CLEAR
3418024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU, FPU_R (and similar MMX/SSE ones)
3419024598e40c84666cc311a42c256bbf880db3ac99sewardj//
3420024598e40c84666cc311a42c256bbf880db3ac99sewardj
3421024598e40c84666cc311a42c256bbf880db3ac99sewardj
3422024598e40c84666cc311a42c256bbf880db3ac99sewardj
3423024598e40c84666cc311a42c256bbf880db3ac99sewardj
3424024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Call h_fn (name h_nm) with the given arg, and return a new IRTemp
3425024598e40c84666cc311a42c256bbf880db3ac99sewardj   holding the result.  The arg must be a word-typed atom.  Callee
3426024598e40c84666cc311a42c256bbf880db3ac99sewardj   must be a VG_REGPARM(1) function. */
3427024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((noinline))
3428024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3429024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr* a1 )
3430024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3431024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3432024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3433024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3434024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3435024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3436024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 1/*regparms*/,
3437024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3438024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_1( a1 ) );
3439024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3440024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3441024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3442024598e40c84666cc311a42c256bbf880db3ac99sewardj
3443024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Two-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(2)
3444024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3445024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3446024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a1, IRExpr* a2 )
3447024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3448024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3449024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3450024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3451024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3452024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3453024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3454024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3455024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 2/*regparms*/,
3456024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3457024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_2( a1, a2 ) );
3458024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3459024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3460024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3461024598e40c84666cc311a42c256bbf880db3ac99sewardj
3462024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Three-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(3)
3463024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3464024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3465024598e40c84666cc311a42c256bbf880db3ac99sewardj                                IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3466024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3467024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3468024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3469024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3470024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3471024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3472024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3473024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3474024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3475024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3476024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3477024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3478024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_3( a1, a2, a3 ) );
3479024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3480024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3481024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3482024598e40c84666cc311a42c256bbf880db3ac99sewardj
3483024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Four-arg version of gen_dirty_W_W.  Callee must be a VG_REGPARM(3)
3484024598e40c84666cc311a42c256bbf880db3ac99sewardj   function.*/
3485024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3486024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 IRExpr* a1, IRExpr* a2,
3487024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 IRExpr* a3, IRExpr* a4 )
3488024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3489024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp   res;
3490024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3491024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3492024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3493024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3494024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3495024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3496024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3497024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3498024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3499024598e40c84666cc311a42c256bbf880db3ac99sewardj   res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3500024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3501024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3502024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_4( a1, a2, a3, a4 ) );
3503024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3504024598e40c84666cc311a42c256bbf880db3ac99sewardj   return res;
3505024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3506024598e40c84666cc311a42c256bbf880db3ac99sewardj
3507024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WW with no return value.  Callee must be a
3508024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(2) function.*/
3509024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3510024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a1, IRExpr* a2 )
3511024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3512024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3513024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3514024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3515024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3516024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3517024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 2/*regparms*/,
3518024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3519024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_2( a1, a2 ) );
3520024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3521024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3522024598e40c84666cc311a42c256bbf880db3ac99sewardj
3523024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WWW with no return value.  Callee must be a
3524024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3525024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3526024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3527024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3528024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3529024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3530024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3531024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3532024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3533024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3534024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3535024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3536024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3537024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_3( a1, a2, a3 ) );
3538024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3539024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3540024598e40c84666cc311a42c256bbf880db3ac99sewardj
3541024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 4 arguments.  Callee must be a
3542024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3543024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3544024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a1, IRExpr* a2,
3545024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr* a3, IRExpr* a4 )
3546024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3547024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3548024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3549024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3550024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3551024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3552024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3553024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3554024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3555024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3556024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3557024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3558024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_4( a1, a2, a3, a4 ) );
3559024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3560024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3561024598e40c84666cc311a42c256bbf880db3ac99sewardj
3562024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 6 arguments.  Callee must be a
3563024598e40c84666cc311a42c256bbf880db3ac99sewardj   VG_REGPARM(3) function.*/
3564024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3565024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a1, IRExpr* a2, IRExpr* a3,
3566024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr* a4, IRExpr* a5, IRExpr* a6 )
3567024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3568024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRDirty* di;
3569024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a1));
3570024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a2));
3571024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a3));
3572024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a4));
3573024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a5));
3574024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a6));
3575024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3576024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3577024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3578024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3579024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a5) == pce->gWordTy);
3580024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(typeOfIRExpr(pce->bb->tyenv, a6) == pce->gWordTy);
3581024598e40c84666cc311a42c256bbf880db3ac99sewardj   di = unsafeIRDirty_0_N( 3/*regparms*/,
3582024598e40c84666cc311a42c256bbf880db3ac99sewardj                           h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3583024598e40c84666cc311a42c256bbf880db3ac99sewardj                           mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) );
3584024598e40c84666cc311a42c256bbf880db3ac99sewardj   stmt( 'I', pce, IRStmt_Dirty(di) );
3585024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3586024598e40c84666cc311a42c256bbf880db3ac99sewardj
3587024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a )
3588024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3589024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRType a_ty = typeOfIRExpr(pce->bb->tyenv, a);
3590024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isIRAtom(a));
3591024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->hWordTy == Ity_I32) {
3592024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (a_ty) {
3593024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I8:
3594024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) );
3595024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I16:
3596024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) );
3597024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3598024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType(a_ty);
3599024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3600024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3601024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3602024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->hWordTy == Ity_I64);
3603024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (a_ty) {
3604024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I8:
3605024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) );
3606024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I16:
3607024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) );
3608024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Ity_I32:
3609024598e40c84666cc311a42c256bbf880db3ac99sewardj            return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) );
3610024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3611024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType(a_ty);
3612024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3613024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3614024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3615024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3616024598e40c84666cc311a42c256bbf880db3ac99sewardj
3617024598e40c84666cc311a42c256bbf880db3ac99sewardj/* 'e' is a word-sized atom.  Call nonptr_or_unknown with it, bind the
3618024598e40c84666cc311a42c256bbf880db3ac99sewardj   results to a new temporary, and return the temporary.  Note this
3619024598e40c84666cc311a42c256bbf880db3ac99sewardj   takes an original expression but returns a shadow value. */
3620024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e )
3621024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3622024598e40c84666cc311a42c256bbf880db3ac99sewardj   return gen_dirty_W_W( pce, &nonptr_or_unknown,
3623024598e40c84666cc311a42c256bbf880db3ac99sewardj                              "nonptr_or_unknown", e );
3624024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3625024598e40c84666cc311a42c256bbf880db3ac99sewardj
3626024598e40c84666cc311a42c256bbf880db3ac99sewardj
3627024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Generate the shadow value for an IRExpr which is an atom and
3628024598e40c84666cc311a42c256bbf880db3ac99sewardj   guaranteed to be word-sized. */
3629024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e )
3630024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3631024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->gWordTy == Ity_I32) {
3632024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) {
3633024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp t;
3634024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(sizeof(UWord) == 4);
3635024598e40c84666cc311a42c256bbf880db3ac99sewardj         t = gen_call_nonptr_or_unknown_w(pce, e);
3636024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr(t);
3637024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3638024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_RdTmp
3639024598e40c84666cc311a42c256bbf880db3ac99sewardj          && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I32) {
3640024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3641024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3642024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* there are no other word-sized atom cases */
3643024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3644024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) {
3645024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp t;
3646024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(sizeof(UWord) == 8);
3647024598e40c84666cc311a42c256bbf880db3ac99sewardj         //return mkU64( (ULong)(UWord)NONPTR );
3648024598e40c84666cc311a42c256bbf880db3ac99sewardj         t = gen_call_nonptr_or_unknown_w(pce, e);
3649024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr(t);
3650024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3651024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (e->tag == Iex_RdTmp
3652024598e40c84666cc311a42c256bbf880db3ac99sewardj          && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I64) {
3653024598e40c84666cc311a42c256bbf880db3ac99sewardj         return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3654024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3655024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* there are no other word-sized atom cases */
3656024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3657024598e40c84666cc311a42c256bbf880db3ac99sewardj   ppIRExpr(e);
3658024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(0);
3659024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3660024598e40c84666cc311a42c256bbf880db3ac99sewardj
3661024598e40c84666cc311a42c256bbf880db3ac99sewardj
3662024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
3663024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid instrument_arithop ( PCEnv* pce,
3664024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRTemp dst, /* already holds result */
3665024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRTemp dstv, /* generate an assignment to this */
3666024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IROp op,
3667024598e40c84666cc311a42c256bbf880db3ac99sewardj                          /* original args, guaranteed to be atoms */
3668024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 )
3669024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3670024598e40c84666cc311a42c256bbf880db3ac99sewardj   HChar*  nm  = NULL;
3671024598e40c84666cc311a42c256bbf880db3ac99sewardj   void*   fn  = NULL;
3672024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRExpr* a1v = NULL;
3673024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRExpr* a2v = NULL;
3674024598e40c84666cc311a42c256bbf880db3ac99sewardj   //IRExpr* a3v = NULL;
3675024598e40c84666cc311a42c256bbf880db3ac99sewardj   //IRExpr* a4v = NULL;
3676024598e40c84666cc311a42c256bbf880db3ac99sewardj   IRTemp  res = IRTemp_INVALID;
3677024598e40c84666cc311a42c256bbf880db3ac99sewardj
3678024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (pce->gWordTy == Ity_I32) {
3679024598e40c84666cc311a42c256bbf880db3ac99sewardj
3680024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->hWordTy == Ity_I32);
3681024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (op) {
3682024598e40c84666cc311a42c256bbf880db3ac99sewardj
3683024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* For these cases, pass Segs for both arguments, and the
3684024598e40c84666cc311a42c256bbf880db3ac99sewardj            result value. */
3685024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32;
3686024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32;
3687024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Or32:  nm = "do_orW";  fn = &do_orW;  goto ssr32;
3688024598e40c84666cc311a42c256bbf880db3ac99sewardj         ssr32:
3689024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3690024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3691024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3692024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3693024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3694024598e40c84666cc311a42c256bbf880db3ac99sewardj
3695024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* In this case, pass Segs for both arguments, the result
3696024598e40c84666cc311a42c256bbf880db3ac99sewardj            value, and the difference between the (original) values of
3697024598e40c84666cc311a42c256bbf880db3ac99sewardj            the arguments. */
3698024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_And32:
3699024598e40c84666cc311a42c256bbf880db3ac99sewardj            nm = "do_andW"; fn = &do_andW;
3700024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3701024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3702024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWWW(
3703024598e40c84666cc311a42c256bbf880db3ac99sewardj                     pce, fn, nm, a1v, a2v, mkexpr(dst),
3704024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assignNew( 'I', pce, Ity_I32,
3705024598e40c84666cc311a42c256bbf880db3ac99sewardj                                binop(Iop_Sub32,a1,a2) ) );
3706024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3707024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3708024598e40c84666cc311a42c256bbf880db3ac99sewardj
3709024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass one shadow arg and the result to the helper. */
3710024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32;
3711024598e40c84666cc311a42c256bbf880db3ac99sewardj         vr32:
3712024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3713024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3714024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3715024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3716024598e40c84666cc311a42c256bbf880db3ac99sewardj
3717024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass two shadow args only to the helper. */
3718024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32;
3719024598e40c84666cc311a42c256bbf880db3ac99sewardj         vv32:
3720024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3721024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3722024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3723024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3724024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3725024598e40c84666cc311a42c256bbf880db3ac99sewardj
3726024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We don't really know what the result could be; test at run
3727024598e40c84666cc311a42c256bbf880db3ac99sewardj            time. */
3728024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_64HIto32: goto n_or_u_32;
3729024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_64to32:   goto n_or_u_32;
3730024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Xor32:    goto n_or_u_32;
3731024598e40c84666cc311a42c256bbf880db3ac99sewardj         n_or_u_32:
3732024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv,
3733024598e40c84666cc311a42c256bbf880db3ac99sewardj                    mkexpr(
3734024598e40c84666cc311a42c256bbf880db3ac99sewardj                       gen_call_nonptr_or_unknown_w( pce,
3735024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                     mkexpr(dst) ) ) );
3736024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3737024598e40c84666cc311a42c256bbf880db3ac99sewardj
3738024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Cases where it's very obvious that the result cannot be a
3739024598e40c84666cc311a42c256bbf880db3ac99sewardj            pointer.  Hence declare directly that it's NONPTR; don't
3740024598e40c84666cc311a42c256bbf880db3ac99sewardj            bother with the overhead of calling nonptr_or_unknown. */
3741024598e40c84666cc311a42c256bbf880db3ac99sewardj
3742024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where it makes no sense for the result to be a ptr */
3743024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3744024598e40c84666cc311a42c256bbf880db3ac99sewardj            arg, so that shift by zero preserves the original
3745024598e40c84666cc311a42c256bbf880db3ac99sewardj            value. */
3746024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shl32:    goto n32;
3747024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sar32:    goto n32;
3748024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shr32:    goto n32;
3749024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Uto32:  goto n32;
3750024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Sto32:  goto n32;
3751024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_F64toI32: goto n32;
3752024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16HLto32: goto n32;
3753024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullS16:  goto n32;
3754024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullU16:  goto n32;
3755024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_PRemC3210F64: goto n32;
3756024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivU32:   goto n32;
3757024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivS32:   goto n32;
3758024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128to32: goto n32;
3759024598e40c84666cc311a42c256bbf880db3ac99sewardj
3760024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where result range is very limited and clearly cannot
3761024598e40c84666cc311a42c256bbf880db3ac99sewardj            be a pointer */
3762024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Uto32: goto n32;
3763024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Sto32: goto n32;
3764024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Uto32: goto n32;
3765024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Sto32: goto n32;
3766024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Clz32:  goto n32;
3767024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Ctz32:  goto n32;
3768024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpF64: goto n32;
3769024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD32S: goto n32;
3770024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD32U: goto n32;
3771024598e40c84666cc311a42c256bbf880db3ac99sewardj         n32:
3772024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
3773024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3774024598e40c84666cc311a42c256bbf880db3ac99sewardj
3775024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3776024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("instrument_arithop(32-bit): unhandled: ");
3777024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIROp(op);
3778024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3779024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3780024598e40c84666cc311a42c256bbf880db3ac99sewardj
3781024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
3782024598e40c84666cc311a42c256bbf880db3ac99sewardj
3783024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(pce->gWordTy == Ity_I64);
3784024598e40c84666cc311a42c256bbf880db3ac99sewardj      switch (op) {
3785024598e40c84666cc311a42c256bbf880db3ac99sewardj
3786024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* For these cases, pass Segs for both arguments, and the
3787024598e40c84666cc311a42c256bbf880db3ac99sewardj            result value. */
3788024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64;
3789024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64;
3790024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Or64:  nm = "do_orW";  fn = &do_orW;  goto ssr64;
3791024598e40c84666cc311a42c256bbf880db3ac99sewardj         ssr64:
3792024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3793024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3794024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3795024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3796024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3797024598e40c84666cc311a42c256bbf880db3ac99sewardj
3798024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* In this case, pass Segs for both arguments, the result
3799024598e40c84666cc311a42c256bbf880db3ac99sewardj            value, and the difference between the (original) values of
3800024598e40c84666cc311a42c256bbf880db3ac99sewardj            the arguments. */
3801024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_And64:
3802024598e40c84666cc311a42c256bbf880db3ac99sewardj            nm = "do_andW"; fn = &do_andW;
3803024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3804024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3805024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WWWW(
3806024598e40c84666cc311a42c256bbf880db3ac99sewardj                     pce, fn, nm, a1v, a2v, mkexpr(dst),
3807024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assignNew( 'I', pce, Ity_I64,
3808024598e40c84666cc311a42c256bbf880db3ac99sewardj                                binop(Iop_Sub64,a1,a2) ) );
3809024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3810024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3811024598e40c84666cc311a42c256bbf880db3ac99sewardj
3812024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass one shadow arg and the result to the helper. */
3813024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64;
3814024598e40c84666cc311a42c256bbf880db3ac99sewardj         vr64:
3815024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3816024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3817024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3818024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3819024598e40c84666cc311a42c256bbf880db3ac99sewardj
3820024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Pass two shadow args only to the helper. */
3821024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64;
3822024598e40c84666cc311a42c256bbf880db3ac99sewardj         vv64:
3823024598e40c84666cc311a42c256bbf880db3ac99sewardj            a1v = schemeEw_Atom( pce, a1 );
3824024598e40c84666cc311a42c256bbf880db3ac99sewardj            a2v = schemeEw_Atom( pce, a2 );
3825024598e40c84666cc311a42c256bbf880db3ac99sewardj            res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3826024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkexpr(res) );
3827024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3828024598e40c84666cc311a42c256bbf880db3ac99sewardj
3829024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We don't really know what the result could be; test at run
3830024598e40c84666cc311a42c256bbf880db3ac99sewardj            time. */
3831024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Xor64:      goto n_or_u_64;
3832024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_128HIto64:  goto n_or_u_64;
3833024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_128to64:    goto n_or_u_64;
3834024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128HIto64: goto n_or_u_64;
3835024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_V128to64:   goto n_or_u_64;
3836024598e40c84666cc311a42c256bbf880db3ac99sewardj         n_or_u_64:
3837024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv,
3838024598e40c84666cc311a42c256bbf880db3ac99sewardj                    mkexpr(
3839024598e40c84666cc311a42c256bbf880db3ac99sewardj                       gen_call_nonptr_or_unknown_w( pce,
3840024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                     mkexpr(dst) ) ) );
3841024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3842024598e40c84666cc311a42c256bbf880db3ac99sewardj
3843024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* Cases where it's very obvious that the result cannot be a
3844024598e40c84666cc311a42c256bbf880db3ac99sewardj            pointer.  Hence declare directly that it's NONPTR; don't
3845024598e40c84666cc311a42c256bbf880db3ac99sewardj            bother with the overhead of calling nonptr_or_unknown. */
3846024598e40c84666cc311a42c256bbf880db3ac99sewardj
3847024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where it makes no sense for the result to be a ptr */
3848024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3849024598e40c84666cc311a42c256bbf880db3ac99sewardj            arg, so that shift by zero preserves the original
3850024598e40c84666cc311a42c256bbf880db3ac99sewardj            value. */
3851024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shl64:      goto n64;
3852024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Sar64:      goto n64;
3853024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Shr64:      goto n64;
3854024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32Uto64:    goto n64;
3855024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32Sto64:    goto n64;
3856024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Uto64:    goto n64;
3857024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_16Sto64:    goto n64;
3858024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_32HLto64:   goto n64;
3859024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivModU64to32: goto n64;
3860024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivModS64to32: goto n64;
3861024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_F64toI64:      goto n64;
3862024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullS32:    goto n64;
3863024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_MullU32:    goto n64;
3864024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivU64:     goto n64;
3865024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_DivS64:     goto n64;
3866024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_ReinterpF64asI64: goto n64;
3867024598e40c84666cc311a42c256bbf880db3ac99sewardj
3868024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* cases where result range is very limited and clearly cannot
3869024598e40c84666cc311a42c256bbf880db3ac99sewardj            be a pointer */
3870024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_1Uto64:        goto n64;
3871024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Uto64:        goto n64;
3872024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_8Sto64:        goto n64;
3873024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Ctz64:         goto n64;
3874024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Clz64:         goto n64;
3875024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD64S:     goto n64;
3876024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpORD64U:     goto n64;
3877024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* 64-bit simd */
3878024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Avg8Ux8: case Iop_Avg16Ux4:
3879024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4:
3880024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Min8Ux8: case Iop_MulHi16Ux4:
3881024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4:
3882024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2:
3883024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8:
3884024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8:
3885024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8:
3886024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4:
3887024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4:
3888024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2:
3889024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2:
3890024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8:
3891024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8:
3892024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4:
3893024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2:
3894024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_InterleaveLO16x4: case Iop_SarN8x8:
3895024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2:
3896024598e40c84666cc311a42c256bbf880db3ac99sewardj         case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4:
3897024598e40c84666cc311a42c256bbf880db3ac99sewardj         n64:
3898024598e40c84666cc311a42c256bbf880db3ac99sewardj            assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
3899024598e40c84666cc311a42c256bbf880db3ac99sewardj            break;
3900024598e40c84666cc311a42c256bbf880db3ac99sewardj
3901024598e40c84666cc311a42c256bbf880db3ac99sewardj         default:
3902024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("instrument_arithop(64-bit): unhandled: ");
3903024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIROp(op);
3904024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(0);
3905024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
3906024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3907024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3908024598e40c84666cc311a42c256bbf880db3ac99sewardj
3909024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic
3910024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid gen_call_nonptr_or_unknown_range ( PCEnv* pce,
3911024598e40c84666cc311a42c256bbf880db3ac99sewardj                                        IRAtom* addr, IRAtom* len )
3912024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3913024598e40c84666cc311a42c256bbf880db3ac99sewardj   gen_dirty_v_WW( pce,
3914024598e40c84666cc311a42c256bbf880db3ac99sewardj                   &nonptr_or_unknown_range,
3915024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "nonptr_or_unknown_range",
3916024598e40c84666cc311a42c256bbf880db3ac99sewardj                   addr, len );
3917024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3918024598e40c84666cc311a42c256bbf880db3ac99sewardj
3919024598e40c84666cc311a42c256bbf880db3ac99sewardj/* iii describes zero or more non-exact integer register updates.  For
3920024598e40c84666cc311a42c256bbf880db3ac99sewardj   each one, generate IR to get the containing register, apply
3921024598e40c84666cc311a42c256bbf880db3ac99sewardj   nonptr_or_unknown to it, and write it back again. */
3922024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii )
3923024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3924024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int i;
3925024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(iii && iii->n_offsets >= 0);
3926024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < iii->n_offsets; i++) {
3927024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy,
3928024598e40c84666cc311a42c256bbf880db3ac99sewardj                              IRExpr_Get( iii->offsets[i], pce->gWordTy ));
3929024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
3930024598e40c84666cc311a42c256bbf880db3ac99sewardj      stmt( 'I', pce, IRStmt_Put( iii->offsets[i]
3931024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     + pce->guest_state_sizeB,
3932024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  mkexpr(a2) ));
3933024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
3934024598e40c84666cc311a42c256bbf880db3ac99sewardj}
3935024598e40c84666cc311a42c256bbf880db3ac99sewardj
3936024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Generate into 'ane', instrumentation for 'st'.  Also copy 'st'
3937024598e40c84666cc311a42c256bbf880db3ac99sewardj   itself into 'ane' (the caller does not do so).  This is somewhat
3938024598e40c84666cc311a42c256bbf880db3ac99sewardj   complex and relies heavily on the assumption that the incoming IR
3939024598e40c84666cc311a42c256bbf880db3ac99sewardj   is in flat form.
3940024598e40c84666cc311a42c256bbf880db3ac99sewardj
3941024598e40c84666cc311a42c256bbf880db3ac99sewardj   Generally speaking, the instrumentation is placed after the
3942024598e40c84666cc311a42c256bbf880db3ac99sewardj   original statement, so that results computed by the original can be
3943024598e40c84666cc311a42c256bbf880db3ac99sewardj   used in the instrumentation.  However, that isn't safe for memory
3944024598e40c84666cc311a42c256bbf880db3ac99sewardj   references, since we need the instrumentation (hence bounds check
3945024598e40c84666cc311a42c256bbf880db3ac99sewardj   and potential error message) to happen before the reference itself,
3946024598e40c84666cc311a42c256bbf880db3ac99sewardj   as the latter could cause a fault. */
3947024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void schemeS ( PCEnv* pce, IRStmt* st )
3948024598e40c84666cc311a42c256bbf880db3ac99sewardj{
3949024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(st);
3950024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(isFlatIRStmt(st));
3951024598e40c84666cc311a42c256bbf880db3ac99sewardj
3952024598e40c84666cc311a42c256bbf880db3ac99sewardj   switch (st->tag) {
3953024598e40c84666cc311a42c256bbf880db3ac99sewardj
3954024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Dirty: {
3955024598e40c84666cc311a42c256bbf880db3ac99sewardj         Int i;
3956024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRDirty* di;
3957024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
3958024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* nasty.  assumes that (1) all helpers are unconditional,
3959024598e40c84666cc311a42c256bbf880db3ac99sewardj            and (2) all outputs are non-ptr */
3960024598e40c84666cc311a42c256bbf880db3ac99sewardj         di = st->Ist.Dirty.details;
3961024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* deal with the return tmp, if any */
3962024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (di->tmp != IRTemp_INVALID
3963024598e40c84666cc311a42c256bbf880db3ac99sewardj             && typeOfIRTemp(pce->bb->tyenv, di->tmp) == pce->gWordTy) {
3964024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* di->tmp is shadowed.  Set it to NONPTR. */
3965024598e40c84666cc311a42c256bbf880db3ac99sewardj            IRTemp dstv = newShadowTmp( pce, di->tmp );
3966024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (pce->gWordTy == Ity_I32) {
3967024598e40c84666cc311a42c256bbf880db3ac99sewardj              assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
3968024598e40c84666cc311a42c256bbf880db3ac99sewardj            } else {
3969024598e40c84666cc311a42c256bbf880db3ac99sewardj              assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
3970024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
3971024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
3972024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* apply the nonptr_or_unknown technique to any parts of
3973024598e40c84666cc311a42c256bbf880db3ac99sewardj            the guest state that happen to get written */
3974024598e40c84666cc311a42c256bbf880db3ac99sewardj         for (i = 0; i < di->nFxState; i++) {
3975024598e40c84666cc311a42c256bbf880db3ac99sewardj            IntRegInfo iii;
3976024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->fxState[i].fx != Ifx_None);
3977024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (di->fxState[i].fx == Ifx_Read)
3978024598e40c84666cc311a42c256bbf880db3ac99sewardj               continue; /* this bit is only read -- not interesting */
3979024598e40c84666cc311a42c256bbf880db3ac99sewardj            get_IntRegInfo( &iii, di->fxState[i].offset,
3980024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  di->fxState[i].size );
3981024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(iii.n_offsets >= -1
3982024598e40c84666cc311a42c256bbf880db3ac99sewardj                      && iii.n_offsets <= N_INTREGINFO_OFFSETS);
3983024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* Deal with 3 possible cases, same as with Ist_Put
3984024598e40c84666cc311a42c256bbf880db3ac99sewardj               elsewhere in this function. */
3985024598e40c84666cc311a42c256bbf880db3ac99sewardj            if (iii.n_offsets == -1) {
3986024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* case (1): exact write of an integer register. */
3987024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRAtom* a1
3988024598e40c84666cc311a42c256bbf880db3ac99sewardj                  = assignNew( 'I', pce, pce->gWordTy,
3989024598e40c84666cc311a42c256bbf880db3ac99sewardj                               IRExpr_Get( iii.offsets[i], pce->gWordTy ));
3990024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
3991024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'I', pce, IRStmt_Put( iii.offsets[i]
3992024598e40c84666cc311a42c256bbf880db3ac99sewardj                                              + pce->guest_state_sizeB,
3993024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           mkexpr(a2) ));
3994024598e40c84666cc311a42c256bbf880db3ac99sewardj            } else {
3995024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* when == 0: case (3): no instrumentation needed */
3996024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* when > 0: case (2) .. complex case.  Fish out the
3997024598e40c84666cc311a42c256bbf880db3ac99sewardj                  stored value for the whole register, heave it
3998024598e40c84666cc311a42c256bbf880db3ac99sewardj                  through nonptr_or_unknown, and use that as the new
3999024598e40c84666cc311a42c256bbf880db3ac99sewardj                  shadow value. */
4000024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(iii.n_offsets >= 0
4001024598e40c84666cc311a42c256bbf880db3ac99sewardj                         && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4002024598e40c84666cc311a42c256bbf880db3ac99sewardj               gen_nonptr_or_unknown_for_III( pce, &iii );
4003024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4004024598e40c84666cc311a42c256bbf880db3ac99sewardj         } /* for (i = 0; i < di->nFxState; i++) */
4005024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* finally, deal with memory outputs */
4006024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (di->mFx != Ifx_None) {
4007024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->mAddr && isIRAtom(di->mAddr));
4008024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(di->mSize > 0);
4009024598e40c84666cc311a42c256bbf880db3ac99sewardj            gen_call_nonptr_or_unknown_range( pce, di->mAddr,
4010024598e40c84666cc311a42c256bbf880db3ac99sewardj                                              mkIRExpr_HWord(di->mSize));
4011024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4012024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4013024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4014024598e40c84666cc311a42c256bbf880db3ac99sewardj
4015024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_NoOp:
4016024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4017024598e40c84666cc311a42c256bbf880db3ac99sewardj
4018024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* nothing interesting in these; just copy them through */
4019024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_AbiHint:
4020024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_MBE:
4021024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Exit:
4022024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_IMark:
4023024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4024024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4025024598e40c84666cc311a42c256bbf880db3ac99sewardj
4026024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_PutI: {
4027024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRRegArray* descr = st->Ist.PutI.descr;
4028024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4029024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(descr && descr->elemTy);
4030024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (is_integer_guest_reg_array(descr)) {
4031024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* if this fails, is_integer_guest_reg_array is returning
4032024598e40c84666cc311a42c256bbf880db3ac99sewardj               bogus results */
4033024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(descr->elemTy == pce->gWordTy);
4034024598e40c84666cc311a42c256bbf880db3ac99sewardj            stmt(
4035024598e40c84666cc311a42c256bbf880db3ac99sewardj               'I', pce,
4036024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRStmt_PutI(
4037024598e40c84666cc311a42c256bbf880db3ac99sewardj                  mkIRRegArray(descr->base + pce->guest_state_sizeB,
4038024598e40c84666cc311a42c256bbf880db3ac99sewardj                               descr->elemTy, descr->nElems),
4039024598e40c84666cc311a42c256bbf880db3ac99sewardj                  st->Ist.PutI.ix,
4040024598e40c84666cc311a42c256bbf880db3ac99sewardj                  st->Ist.PutI.bias,
4041024598e40c84666cc311a42c256bbf880db3ac99sewardj                  schemeEw_Atom( pce, st->Ist.PutI.data)
4042024598e40c84666cc311a42c256bbf880db3ac99sewardj               )
4043024598e40c84666cc311a42c256bbf880db3ac99sewardj            );
4044024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4045024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4046024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4047024598e40c84666cc311a42c256bbf880db3ac99sewardj
4048024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Put: {
4049024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* PUT(offset) = atom */
4050024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* 3 cases:
4051024598e40c84666cc311a42c256bbf880db3ac99sewardj            1. It's a complete write of an integer register.  Get hold of
4052024598e40c84666cc311a42c256bbf880db3ac99sewardj               'atom's shadow value and write it in the shadow state.
4053024598e40c84666cc311a42c256bbf880db3ac99sewardj            2. It's a partial write of an integer register.  Let the write
4054024598e40c84666cc311a42c256bbf880db3ac99sewardj               happen, then fish out the complete register value and see if,
4055024598e40c84666cc311a42c256bbf880db3ac99sewardj               via range checking, consultation of tea leaves, etc, its
4056024598e40c84666cc311a42c256bbf880db3ac99sewardj               shadow value can be upgraded to anything useful.
4057024598e40c84666cc311a42c256bbf880db3ac99sewardj            3. It is none of the above.  Generate no instrumentation. */
4058024598e40c84666cc311a42c256bbf880db3ac99sewardj         IntRegInfo iii;
4059024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType     ty;
4060024598e40c84666cc311a42c256bbf880db3ac99sewardj         stmt( 'C', pce, st );
4061024598e40c84666cc311a42c256bbf880db3ac99sewardj         ty = typeOfIRExpr(pce->bb->tyenv, st->Ist.Put.data);
4062024598e40c84666cc311a42c256bbf880db3ac99sewardj         get_IntRegInfo( &iii, st->Ist.Put.offset,
4063024598e40c84666cc311a42c256bbf880db3ac99sewardj                         sizeofIRType(ty) );
4064024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (iii.n_offsets == -1) {
4065024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* case (1): exact write of an integer register. */
4066024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(ty == pce->gWordTy);
4067024598e40c84666cc311a42c256bbf880db3ac99sewardj            stmt( 'I', pce,
4068024598e40c84666cc311a42c256bbf880db3ac99sewardj                       IRStmt_Put( st->Ist.Put.offset
4069024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      + pce->guest_state_sizeB,
4070024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   schemeEw_Atom( pce, st->Ist.Put.data)) );
4071024598e40c84666cc311a42c256bbf880db3ac99sewardj         } else {
4072024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* when == 0: case (3): no instrumentation needed */
4073024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* when > 0: case (2) .. complex case.  Fish out the
4074024598e40c84666cc311a42c256bbf880db3ac99sewardj               stored value for the whole register, heave it through
4075024598e40c84666cc311a42c256bbf880db3ac99sewardj               nonptr_or_unknown, and use that as the new shadow
4076024598e40c84666cc311a42c256bbf880db3ac99sewardj               value. */
4077024598e40c84666cc311a42c256bbf880db3ac99sewardj            tl_assert(iii.n_offsets >= 0
4078024598e40c84666cc311a42c256bbf880db3ac99sewardj                      && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4079024598e40c84666cc311a42c256bbf880db3ac99sewardj            gen_nonptr_or_unknown_for_III( pce, &iii );
4080024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4081024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4082024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_Put */
4083024598e40c84666cc311a42c256bbf880db3ac99sewardj
4084024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_Store: {
4085024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* We have: STle(addr) = data
4086024598e40c84666cc311a42c256bbf880db3ac99sewardj            if data is int-word sized, do
4087024598e40c84666cc311a42c256bbf880db3ac99sewardj            check_store4(addr, addr#, data, data#)
4088024598e40c84666cc311a42c256bbf880db3ac99sewardj            for all other stores
4089024598e40c84666cc311a42c256bbf880db3ac99sewardj            check_store{1,2}(addr, addr#, data)
4090024598e40c84666cc311a42c256bbf880db3ac99sewardj
4091024598e40c84666cc311a42c256bbf880db3ac99sewardj            The helper actually *does* the store, so that it can do
4092024598e40c84666cc311a42c256bbf880db3ac99sewardj            the post-hoc ugly hack of inspecting and "improving" the
4093024598e40c84666cc311a42c256bbf880db3ac99sewardj            shadow data after the store, in the case where it isn't an
4094024598e40c84666cc311a42c256bbf880db3ac99sewardj            aligned word store.
4095024598e40c84666cc311a42c256bbf880db3ac99sewardj         */
4096024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* data  = st->Ist.Store.data;
4097024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* addr  = st->Ist.Store.addr;
4098024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType  d_ty  = typeOfIRExpr(pce->bb->tyenv, data);
4099024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* addrv = schemeEw_Atom( pce, addr );
4100024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (pce->gWordTy == Ity_I32) {
4101024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* ------ 32 bit host/guest (cough, cough) ------ */
4102024598e40c84666cc311a42c256bbf880db3ac99sewardj            switch (d_ty) {
4103024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer word case */
4104024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I32: {
4105024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRExpr* datav = schemeEw_Atom( pce, data );
4106024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4107024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store4_P, "check_store4_P",
4108024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, data, datav );
4109024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4110024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4111024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer subword cases */
4112024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I16:
4113024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4114024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store2, "check_store2",
4115024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4116024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4117024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4118024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I8:
4119024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4120024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store1, "check_store1",
4121024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4122024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4123024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4124024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit float.  Pass store data in 2 32-bit pieces. */
4125024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F64: {
4126024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* d64 = assignNew( 'I', pce, Ity_I64,
4127024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF64asI64, data) );
4128024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4129024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, d64) );
4130024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4131024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, d64) );
4132024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4133024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_ms4B_ls4B,
4134024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store8_ms4B_ls4B",
4135024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi32, dLo32 );
4136024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4137024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4138024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 32-bit float.  We can just use _store4, but need
4139024598e40c84666cc311a42c256bbf880db3ac99sewardj                  to futz with the argument type. */
4140024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F32: {
4141024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4142024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF32asI32,
4143024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4144024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4145024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4,
4146024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store4",
4147024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, i32 );
4148024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4149024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4150024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit int.  Pass store data in 2 32-bit pieces. */
4151024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I64: {
4152024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4153024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, data) );
4154024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4155024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, data) );
4156024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4157024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_ms4B_ls4B,
4158024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store8_ms4B_ls4B",
4159024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi32, dLo32 );
4160024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4161024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4162024598e40c84666cc311a42c256bbf880db3ac99sewardj
4163024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 128-bit vector.  Pass store data in 4 32-bit pieces.
4164024598e40c84666cc311a42c256bbf880db3ac99sewardj                  This is all very ugly and inefficient, but it is
4165024598e40c84666cc311a42c256bbf880db3ac99sewardj                  hard to better without considerably complicating the
4166024598e40c84666cc311a42c256bbf880db3ac99sewardj                  store-handling schemes. */
4167024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_V128: {
4168024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4169024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128HIto64, data) );
4170024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4171024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128to64, data) );
4172024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w3    = assignNew( 'I', pce, Ity_I32,
4173024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, dHi64) );
4174024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w2    = assignNew( 'I', pce, Ity_I32,
4175024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, dHi64) );
4176024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w1    = assignNew( 'I', pce, Ity_I32,
4177024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64HIto32, dLo64) );
4178024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* w0    = assignNew( 'I', pce, Ity_I32,
4179024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_64to32, dLo64) );
4180024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_6W( pce,
4181024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  &check_store16_ms4B_4B_4B_ls4B,
4182024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  "check_store16_ms4B_4B_4B_ls4B",
4183024598e40c84666cc311a42c256bbf880db3ac99sewardj                                  addr, addrv, w3, w2, w1, w0 );
4184024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4185024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4186024598e40c84666cc311a42c256bbf880db3ac99sewardj
4187024598e40c84666cc311a42c256bbf880db3ac99sewardj
4188024598e40c84666cc311a42c256bbf880db3ac99sewardj               default:
4189024598e40c84666cc311a42c256bbf880db3ac99sewardj                  ppIRType(d_ty); tl_assert(0);
4190024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4191024598e40c84666cc311a42c256bbf880db3ac99sewardj         } else {
4192024598e40c84666cc311a42c256bbf880db3ac99sewardj            /* ------ 64 bit host/guest (cough, cough) ------ */
4193024598e40c84666cc311a42c256bbf880db3ac99sewardj            switch (d_ty) {
4194024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer word case */
4195024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I64: {
4196024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRExpr* datav = schemeEw_Atom( pce, data );
4197024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4198024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store8_P, "check_store8_P",
4199024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, data, datav );
4200024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4201024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4202024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Integer subword cases */
4203024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I32:
4204024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4205024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4, "check_store4",
4206024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4207024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4208024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4209024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I16:
4210024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4211024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store2, "check_store2",
4212024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4213024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4214024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4215024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_I8:
4216024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4217024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store1, "check_store1",
4218024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv,
4219024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   uwiden_to_host_word( pce, data ));
4220024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4221024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 128-bit vector.  Pass store data in 2 64-bit pieces. */
4222024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_V128: {
4223024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4224024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128HIto64, data) );
4225024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4226024598e40c84666cc311a42c256bbf880db3ac99sewardj                                             unop(Iop_V128to64, data) );
4227024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWWW( pce,
4228024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    &check_store16_ms8B_ls8B,
4229024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    "check_store16_ms8B_ls8B",
4230024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    addr, addrv, dHi64, dLo64 );
4231024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4232024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4233024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 64-bit float. */
4234024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F64: {
4235024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* dI = assignNew( 'I', pce, Ity_I64,
4236024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF64asI64,
4237024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4238024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4239024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store8_all8B,
4240024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store8_all8B",
4241024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, dI );
4242024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4243024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4244024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* 32-bit float.  We can just use _store4, but need
4245024598e40c84666cc311a42c256bbf880db3ac99sewardj                  to futz with the argument type. */
4246024598e40c84666cc311a42c256bbf880db3ac99sewardj               case Ity_F32: {
4247024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4248024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_ReinterpF32asI32,
4249024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                data ) );
4250024598e40c84666cc311a42c256bbf880db3ac99sewardj                  IRAtom* i64 = assignNew( 'I', pce, Ity_I64,
4251024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           unop(Iop_32Uto64,
4252024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                i32 ) );
4253024598e40c84666cc311a42c256bbf880db3ac99sewardj                  gen_dirty_v_WWW( pce,
4254024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   &check_store4,
4255024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   "check_store4",
4256024598e40c84666cc311a42c256bbf880db3ac99sewardj                                   addr, addrv, i64 );
4257024598e40c84666cc311a42c256bbf880db3ac99sewardj                  break;
4258024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4259024598e40c84666cc311a42c256bbf880db3ac99sewardj               default:
4260024598e40c84666cc311a42c256bbf880db3ac99sewardj                  ppIRType(d_ty); tl_assert(0);
4261024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4262024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4263024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* And don't copy the original, since the helper does the
4264024598e40c84666cc311a42c256bbf880db3ac99sewardj            store.  Ick. */
4265024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4266024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_Store */
4267024598e40c84666cc311a42c256bbf880db3ac99sewardj
4268024598e40c84666cc311a42c256bbf880db3ac99sewardj      case Ist_WrTmp: {
4269024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* This is the only place we have to deal with the full
4270024598e40c84666cc311a42c256bbf880db3ac99sewardj            IRExpr range.  In all other places where an IRExpr could
4271024598e40c84666cc311a42c256bbf880db3ac99sewardj            appear, we in fact only get an atom (Iex_RdTmp or
4272024598e40c84666cc311a42c256bbf880db3ac99sewardj            Iex_Const). */
4273024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRExpr* e      = st->Ist.WrTmp.data;
4274024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType  e_ty   = typeOfIRExpr( pce->bb->tyenv, e );
4275024598e40c84666cc311a42c256bbf880db3ac99sewardj         Bool    isWord = e_ty == pce->gWordTy;
4276024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp  dst    = st->Ist.WrTmp.tmp;
4277024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp  dstv   = isWord ? newShadowTmp( pce, dst )
4278024598e40c84666cc311a42c256bbf880db3ac99sewardj                                 : IRTemp_INVALID;
4279024598e40c84666cc311a42c256bbf880db3ac99sewardj
4280024598e40c84666cc311a42c256bbf880db3ac99sewardj         switch (e->tag) {
4281024598e40c84666cc311a42c256bbf880db3ac99sewardj
4282024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Const: {
4283024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4284024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4285024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) );
4286024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4287024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4288024598e40c84666cc311a42c256bbf880db3ac99sewardj
4289024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_CCall: {
4290024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4291024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4292024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv,
4293024598e40c84666cc311a42c256bbf880db3ac99sewardj                          mkexpr( gen_call_nonptr_or_unknown_w(
4294024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     pce, mkexpr(dst))));
4295024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4296024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4297024598e40c84666cc311a42c256bbf880db3ac99sewardj
4298024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Mux0X: {
4299024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* Just steer the shadow values in the same way as the
4300024598e40c84666cc311a42c256bbf880db3ac99sewardj                  originals. */
4301024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4302024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4303024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv,
4304024598e40c84666cc311a42c256bbf880db3ac99sewardj                          IRExpr_Mux0X(
4305024598e40c84666cc311a42c256bbf880db3ac99sewardj                             e->Iex.Mux0X.cond,
4306024598e40c84666cc311a42c256bbf880db3ac99sewardj                             schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ),
4307024598e40c84666cc311a42c256bbf880db3ac99sewardj                             schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) ));
4308024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4309024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4310024598e40c84666cc311a42c256bbf880db3ac99sewardj
4311024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_RdTmp: {
4312024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4313024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4314024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign( 'I', pce, dstv, schemeEw_Atom( pce, e ));
4315024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4316024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4317024598e40c84666cc311a42c256bbf880db3ac99sewardj
4318024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Load: {
4319024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRExpr* addr  = e->Iex.Load.addr;
4320024598e40c84666cc311a42c256bbf880db3ac99sewardj               HChar*  h_nm  = NULL;
4321024598e40c84666cc311a42c256bbf880db3ac99sewardj               void*   h_fn  = NULL;
4322024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRExpr* addrv = NULL;
4323024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (pce->gWordTy == Ity_I32) {
4324024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* 32 bit host/guest (cough, cough) */
4325024598e40c84666cc311a42c256bbf880db3ac99sewardj                  switch (e_ty) {
4326024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* Ity_I32: helper returns shadow value. */
4327024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I32:  h_fn = &check_load4_P;
4328024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4_P"; break;
4329024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* all others: helper does not return a shadow
4330024598e40c84666cc311a42c256bbf880db3ac99sewardj                        value. */
4331024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_V128: h_fn = &check_load16;
4332024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load16"; break;
4333024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I64:
4334024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F64:  h_fn = &check_load8;
4335024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8"; break;
4336024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F32:  h_fn = &check_load4;
4337024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4"; break;
4338024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I16:  h_fn = &check_load2;
4339024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load2"; break;
4340024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I8:   h_fn = &check_load1;
4341024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load1"; break;
4342024598e40c84666cc311a42c256bbf880db3ac99sewardj                     default: ppIRType(e_ty); tl_assert(0);
4343024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4344024598e40c84666cc311a42c256bbf880db3ac99sewardj                  addrv = schemeEw_Atom( pce, addr );
4345024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (e_ty == Ity_I32) {
4346024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4347024598e40c84666cc311a42c256bbf880db3ac99sewardj                              mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4348024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                           addr, addrv )) );
4349024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4350024598e40c84666cc311a42c256bbf880db3ac99sewardj                     gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4351024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4352024598e40c84666cc311a42c256bbf880db3ac99sewardj               } else {
4353024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* 64 bit host/guest (cough, cough) */
4354024598e40c84666cc311a42c256bbf880db3ac99sewardj                  switch (e_ty) {
4355024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* Ity_I64: helper returns shadow value. */
4356024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I64:  h_fn = &check_load8_P;
4357024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8_P"; break;
4358024598e40c84666cc311a42c256bbf880db3ac99sewardj                     /* all others: helper does not return a shadow
4359024598e40c84666cc311a42c256bbf880db3ac99sewardj                        value. */
4360024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_V128: h_fn = &check_load16;
4361024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load16"; break;
4362024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F64:  h_fn = &check_load8;
4363024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load8"; break;
4364024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_F32:
4365024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I32:  h_fn = &check_load4;
4366024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load4"; break;
4367024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I16:  h_fn = &check_load2;
4368024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load2"; break;
4369024598e40c84666cc311a42c256bbf880db3ac99sewardj                     case Ity_I8:   h_fn = &check_load1;
4370024598e40c84666cc311a42c256bbf880db3ac99sewardj                                    h_nm = "check_load1"; break;
4371024598e40c84666cc311a42c256bbf880db3ac99sewardj                     default: ppIRType(e_ty); tl_assert(0);
4372024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4373024598e40c84666cc311a42c256bbf880db3ac99sewardj                  addrv = schemeEw_Atom( pce, addr );
4374024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (e_ty == Ity_I64) {
4375024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4376024598e40c84666cc311a42c256bbf880db3ac99sewardj                              mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4377024598e40c84666cc311a42c256bbf880db3ac99sewardj                                                           addr, addrv )) );
4378024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4379024598e40c84666cc311a42c256bbf880db3ac99sewardj                     gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4380024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4381024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4382024598e40c84666cc311a42c256bbf880db3ac99sewardj               /* copy the original -- must happen after the helper call */
4383024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4384024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4385024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4386024598e40c84666cc311a42c256bbf880db3ac99sewardj
4387024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_GetI: {
4388024598e40c84666cc311a42c256bbf880db3ac99sewardj               IRRegArray* descr = e->Iex.GetI.descr;
4389024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4390024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(descr && descr->elemTy);
4391024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (is_integer_guest_reg_array(descr)) {
4392024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* if this fails, is_integer_guest_reg_array is
4393024598e40c84666cc311a42c256bbf880db3ac99sewardj                     returning bogus results */
4394024598e40c84666cc311a42c256bbf880db3ac99sewardj                  tl_assert(isWord);
4395024598e40c84666cc311a42c256bbf880db3ac99sewardj                  assign(
4396024598e40c84666cc311a42c256bbf880db3ac99sewardj                     'I', pce, dstv,
4397024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRExpr_GetI(
4398024598e40c84666cc311a42c256bbf880db3ac99sewardj                        mkIRRegArray(descr->base + pce->guest_state_sizeB,
4399024598e40c84666cc311a42c256bbf880db3ac99sewardj                                     descr->elemTy, descr->nElems),
4400024598e40c84666cc311a42c256bbf880db3ac99sewardj                        e->Iex.GetI.ix,
4401024598e40c84666cc311a42c256bbf880db3ac99sewardj                        e->Iex.GetI.bias
4402024598e40c84666cc311a42c256bbf880db3ac99sewardj                     )
4403024598e40c84666cc311a42c256bbf880db3ac99sewardj                  );
4404024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4405024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4406024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4407024598e40c84666cc311a42c256bbf880db3ac99sewardj
4408024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Get: {
4409024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4410024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord) {
4411024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* guest-word-typed tmp assignment, so it will have a
4412024598e40c84666cc311a42c256bbf880db3ac99sewardj                     shadow tmp, and we must make an assignment to
4413024598e40c84666cc311a42c256bbf880db3ac99sewardj                     that */
4414024598e40c84666cc311a42c256bbf880db3ac99sewardj                  if (is_integer_guest_reg(e->Iex.Get.offset,
4415024598e40c84666cc311a42c256bbf880db3ac99sewardj                                           sizeofIRType(e->Iex.Get.ty))) {
4416024598e40c84666cc311a42c256bbf880db3ac99sewardj                     assign( 'I', pce, dstv,
4417024598e40c84666cc311a42c256bbf880db3ac99sewardj                             IRExpr_Get( e->Iex.Get.offset
4418024598e40c84666cc311a42c256bbf880db3ac99sewardj                                            + pce->guest_state_sizeB,
4419024598e40c84666cc311a42c256bbf880db3ac99sewardj                                         e->Iex.Get.ty) );
4420024598e40c84666cc311a42c256bbf880db3ac99sewardj                  } else {
4421024598e40c84666cc311a42c256bbf880db3ac99sewardj                     if (pce->hWordTy == Ity_I32) {
4422024598e40c84666cc311a42c256bbf880db3ac99sewardj                        assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4423024598e40c84666cc311a42c256bbf880db3ac99sewardj                     } else {
4424024598e40c84666cc311a42c256bbf880db3ac99sewardj                       assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4425024598e40c84666cc311a42c256bbf880db3ac99sewardj                     }
4426024598e40c84666cc311a42c256bbf880db3ac99sewardj                  }
4427024598e40c84666cc311a42c256bbf880db3ac99sewardj               } else {
4428024598e40c84666cc311a42c256bbf880db3ac99sewardj                  /* tmp isn't guest-word-typed, so isn't shadowed, so
4429024598e40c84666cc311a42c256bbf880db3ac99sewardj                     generate no instrumentation */
4430024598e40c84666cc311a42c256bbf880db3ac99sewardj               }
4431024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4432024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4433024598e40c84666cc311a42c256bbf880db3ac99sewardj
4434024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Unop: {
4435024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4436024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Unop.arg));
4437024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4438024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Unop.op,
4439024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Unop.arg,
4440024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      NULL, NULL, NULL );
4441024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4442024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4443024598e40c84666cc311a42c256bbf880db3ac99sewardj
4444024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Binop: {
4445024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4446024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Binop.arg1));
4447024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Binop.arg2));
4448024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4449024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Binop.op,
4450024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Binop.arg1, e->Iex.Binop.arg2,
4451024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      NULL, NULL );
4452024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4453024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4454024598e40c84666cc311a42c256bbf880db3ac99sewardj
4455024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Triop: {
4456024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4457024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg1));
4458024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg2));
4459024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Triop.arg3));
4460024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4461024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Triop.op,
4462024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Triop.arg1, e->Iex.Triop.arg2,
4463024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Triop.arg3, NULL );
4464024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4465024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4466024598e40c84666cc311a42c256bbf880db3ac99sewardj
4467024598e40c84666cc311a42c256bbf880db3ac99sewardj            case Iex_Qop: {
4468024598e40c84666cc311a42c256bbf880db3ac99sewardj               stmt( 'C', pce, st );
4469024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg1));
4470024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg2));
4471024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg3));
4472024598e40c84666cc311a42c256bbf880db3ac99sewardj               tl_assert(isIRAtom(e->Iex.Qop.arg4));
4473024598e40c84666cc311a42c256bbf880db3ac99sewardj               if (isWord)
4474024598e40c84666cc311a42c256bbf880db3ac99sewardj                  instrument_arithop( pce, dst, dstv, e->Iex.Qop.op,
4475024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Qop.arg1, e->Iex.Qop.arg2,
4476024598e40c84666cc311a42c256bbf880db3ac99sewardj                                      e->Iex.Qop.arg3, e->Iex.Qop.arg4 );
4477024598e40c84666cc311a42c256bbf880db3ac99sewardj               break;
4478024598e40c84666cc311a42c256bbf880db3ac99sewardj            }
4479024598e40c84666cc311a42c256bbf880db3ac99sewardj
4480024598e40c84666cc311a42c256bbf880db3ac99sewardj            default:
4481024598e40c84666cc311a42c256bbf880db3ac99sewardj               goto unhandled;
4482024598e40c84666cc311a42c256bbf880db3ac99sewardj         } /* switch (e->tag) */
4483024598e40c84666cc311a42c256bbf880db3ac99sewardj
4484024598e40c84666cc311a42c256bbf880db3ac99sewardj         break;
4485024598e40c84666cc311a42c256bbf880db3ac99sewardj
4486024598e40c84666cc311a42c256bbf880db3ac99sewardj      } /* case Ist_WrTmp */
4487024598e40c84666cc311a42c256bbf880db3ac99sewardj
4488024598e40c84666cc311a42c256bbf880db3ac99sewardj      default:
4489024598e40c84666cc311a42c256bbf880db3ac99sewardj      unhandled:
4490024598e40c84666cc311a42c256bbf880db3ac99sewardj         ppIRStmt(st);
4491024598e40c84666cc311a42c256bbf880db3ac99sewardj         tl_assert(0);
4492024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4493024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4494024598e40c84666cc311a42c256bbf880db3ac99sewardj
4495024598e40c84666cc311a42c256bbf880db3ac99sewardj
4496024598e40c84666cc311a42c256bbf880db3ac99sewardjIRSB* h_instrument ( VgCallbackClosure* closure,
4497024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRSB* sbIn,
4498024598e40c84666cc311a42c256bbf880db3ac99sewardj                     VexGuestLayout* layout,
4499024598e40c84666cc311a42c256bbf880db3ac99sewardj                     VexGuestExtents* vge,
4500024598e40c84666cc311a42c256bbf880db3ac99sewardj                     IRType gWordTy, IRType hWordTy )
4501024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4502024598e40c84666cc311a42c256bbf880db3ac99sewardj   Bool  verboze = 0||False;
4503024598e40c84666cc311a42c256bbf880db3ac99sewardj   Int   i /*, j*/;
4504024598e40c84666cc311a42c256bbf880db3ac99sewardj   PCEnv pce;
4505024598e40c84666cc311a42c256bbf880db3ac99sewardj   struct _SGEnv* sgenv;
4506024598e40c84666cc311a42c256bbf880db3ac99sewardj
4507024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (gWordTy != hWordTy) {
4508024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* We don't currently support this case. */
4509024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(tool_panic)("host/guest word size mismatch");
4510024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4511024598e40c84666cc311a42c256bbf880db3ac99sewardj
4512024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Check we're not completely nuts */
4513024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UWord)  == sizeof(void*));
4514024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Word)   == sizeof(void*));
4515024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr)   == sizeof(void*));
4516024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(ULong)  == 8);
4517024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Long)   == 8);
4518024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Addr64) == 8);
4519024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(UInt)   == 4);
4520024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sizeof(Int)    == 4);
4521024598e40c84666cc311a42c256bbf880db3ac99sewardj
4522024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Set up the running environment.  Only .bb is modified as we go
4523024598e40c84666cc311a42c256bbf880db3ac99sewardj      along. */
4524024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.bb                = deepCopyIRSBExceptStmts(sbIn);
4525024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.trace             = verboze;
4526024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.n_originalTmps    = sbIn->tyenv->types_used;
4527024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.hWordTy           = hWordTy;
4528024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.gWordTy           = gWordTy;
4529024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.guest_state_sizeB = layout->total_sizeB;
4530024598e40c84666cc311a42c256bbf880db3ac99sewardj   pce.tmpMap            = LibVEX_Alloc(pce.n_originalTmps * sizeof(IRTemp));
4531024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (i = 0; i < pce.n_originalTmps; i++)
4532024598e40c84666cc311a42c256bbf880db3ac99sewardj      pce.tmpMap[i] = IRTemp_INVALID;
4533024598e40c84666cc311a42c256bbf880db3ac99sewardj
4534024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Also set up for the sg_ instrumenter.  See comments
4535024598e40c84666cc311a42c256bbf880db3ac99sewardj      at the top of this instrumentation section for details. */
4536024598e40c84666cc311a42c256bbf880db3ac99sewardj   sgenv = sg_instrument_init();
4537024598e40c84666cc311a42c256bbf880db3ac99sewardj
4538024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Stay sane.  These two should agree! */
4539024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE);
4540024598e40c84666cc311a42c256bbf880db3ac99sewardj
4541024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Copy verbatim any IR preamble preceding the first IMark */
4542024598e40c84666cc311a42c256bbf880db3ac99sewardj
4543024598e40c84666cc311a42c256bbf880db3ac99sewardj   i = 0;
4544024598e40c84666cc311a42c256bbf880db3ac99sewardj   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
4545024598e40c84666cc311a42c256bbf880db3ac99sewardj      IRStmt* st = sbIn->stmts[i];
4546024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(st);
4547024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert(isFlatIRStmt(st));
4548024598e40c84666cc311a42c256bbf880db3ac99sewardj      stmt( 'C', &pce, sbIn->stmts[i] );
4549024598e40c84666cc311a42c256bbf880db3ac99sewardj      i++;
4550024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4551024598e40c84666cc311a42c256bbf880db3ac99sewardj
4552024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Nasty problem.  IR optimisation of the pre-instrumented IR may
4553024598e40c84666cc311a42c256bbf880db3ac99sewardj      cause the IR following the preamble to contain references to IR
4554024598e40c84666cc311a42c256bbf880db3ac99sewardj      temporaries defined in the preamble.  Because the preamble isn't
4555024598e40c84666cc311a42c256bbf880db3ac99sewardj      instrumented, these temporaries don't have any shadows.
4556024598e40c84666cc311a42c256bbf880db3ac99sewardj      Nevertheless uses of them following the preamble will cause
4557024598e40c84666cc311a42c256bbf880db3ac99sewardj      memcheck to generate references to their shadows.  End effect is
4558024598e40c84666cc311a42c256bbf880db3ac99sewardj      to cause IR sanity check failures, due to references to
4559024598e40c84666cc311a42c256bbf880db3ac99sewardj      non-existent shadows.  This is only evident for the complex
4560024598e40c84666cc311a42c256bbf880db3ac99sewardj      preambles used for function wrapping on TOC-afflicted platforms
4561024598e40c84666cc311a42c256bbf880db3ac99sewardj      (ppc64-linux, ppc32-aix5, ppc64-aix5).
4562024598e40c84666cc311a42c256bbf880db3ac99sewardj
4563024598e40c84666cc311a42c256bbf880db3ac99sewardj      The following loop therefore scans the preamble looking for
4564024598e40c84666cc311a42c256bbf880db3ac99sewardj      assignments to temporaries.  For each one found it creates an
4565024598e40c84666cc311a42c256bbf880db3ac99sewardj      assignment to the corresponding shadow temp, marking it as
4566024598e40c84666cc311a42c256bbf880db3ac99sewardj      'defined'.  This is the same resulting IR as if the main
4567024598e40c84666cc311a42c256bbf880db3ac99sewardj      instrumentation loop before had been applied to the statement
4568024598e40c84666cc311a42c256bbf880db3ac99sewardj      'tmp = CONSTANT'.
4569024598e40c84666cc311a42c256bbf880db3ac99sewardj   */
4570024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0
4571024598e40c84666cc311a42c256bbf880db3ac99sewardj   // FIXME: this isn't exactly right; only needs to generate shadows
4572024598e40c84666cc311a42c256bbf880db3ac99sewardj   // for guest-word-typed temps
4573024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (j = 0; j < i; j++) {
4574024598e40c84666cc311a42c256bbf880db3ac99sewardj      if (sbIn->stmts[j]->tag == Ist_WrTmp) {
4575024598e40c84666cc311a42c256bbf880db3ac99sewardj         /* findShadowTmpV checks its arg is an original tmp;
4576024598e40c84666cc311a42c256bbf880db3ac99sewardj            no need to assert that here. */
4577024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp;
4578024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRTemp tmp_s = findShadowTmp(&pce, tmp_o);
4579024598e40c84666cc311a42c256bbf880db3ac99sewardj         IRType ty_s  = typeOfIRTemp(sbIn->tyenv, tmp_s);
4580024598e40c84666cc311a42c256bbf880db3ac99sewardj         assign( 'V', &pce, tmp_s, definedOfType( ty_s ) );
4581024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (0) {
4582024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
4583024598e40c84666cc311a42c256bbf880db3ac99sewardj            ppIRType( ty_s );
4584024598e40c84666cc311a42c256bbf880db3ac99sewardj            VG_(printf)("\n");
4585024598e40c84666cc311a42c256bbf880db3ac99sewardj         }
4586024598e40c84666cc311a42c256bbf880db3ac99sewardj      }
4587024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4588024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif
4589024598e40c84666cc311a42c256bbf880db3ac99sewardj
4590024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* Iterate over the remaining stmts to generate instrumentation. */
4591024598e40c84666cc311a42c256bbf880db3ac99sewardj
4592024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sbIn->stmts_used > 0);
4593024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i >= 0);
4594024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(i < sbIn->stmts_used);
4595024598e40c84666cc311a42c256bbf880db3ac99sewardj   tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
4596024598e40c84666cc311a42c256bbf880db3ac99sewardj
4597024598e40c84666cc311a42c256bbf880db3ac99sewardj   for (/*use current i*/; i < sbIn->stmts_used; i++) {
4598024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* generate sg_ instrumentation for this stmt */
4599024598e40c84666cc311a42c256bbf880db3ac99sewardj      sg_instrument_IRStmt( sgenv, pce.bb, sbIn->stmts[i],
4600024598e40c84666cc311a42c256bbf880db3ac99sewardj                            layout, gWordTy, hWordTy );
4601024598e40c84666cc311a42c256bbf880db3ac99sewardj      /* generate h_ instrumentation for this stmt */
4602024598e40c84666cc311a42c256bbf880db3ac99sewardj      schemeS( &pce, sbIn->stmts[i] );
4603024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4604024598e40c84666cc311a42c256bbf880db3ac99sewardj
4605024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* generate sg_ instrumentation for the final jump */
4606024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_final_jump( sgenv, pce.bb, sbIn->next, sbIn->jumpkind,
4607024598e40c84666cc311a42c256bbf880db3ac99sewardj                             layout, gWordTy, hWordTy );
4608024598e40c84666cc311a42c256bbf880db3ac99sewardj
4609024598e40c84666cc311a42c256bbf880db3ac99sewardj   /* and finalise .. */
4610024598e40c84666cc311a42c256bbf880db3ac99sewardj   sg_instrument_fini( sgenv );
4611024598e40c84666cc311a42c256bbf880db3ac99sewardj
4612024598e40c84666cc311a42c256bbf880db3ac99sewardj   return pce.bb;
4613024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4614024598e40c84666cc311a42c256bbf880db3ac99sewardj
4615024598e40c84666cc311a42c256bbf880db3ac99sewardj
4616024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4617024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Initialisation                                               ---*/
4618024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4619024598e40c84666cc311a42c256bbf880db3ac99sewardj
4620024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_clo_init ( void )
4621024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4622024598e40c84666cc311a42c256bbf880db3ac99sewardj   // Other initialisation
4623024598e40c84666cc311a42c256bbf880db3ac99sewardj   init_shadow_memory();
4624024598e40c84666cc311a42c256bbf880db3ac99sewardj   init_lossage();
4625024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4626024598e40c84666cc311a42c256bbf880db3ac99sewardj
4627024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_clo_init ( void )
4628024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4629024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4630024598e40c84666cc311a42c256bbf880db3ac99sewardj
4631024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4632024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Finalisation                                                 ---*/
4633024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4634024598e40c84666cc311a42c256bbf880db3ac99sewardj
4635024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_fini ( Int exitcode )
4636024598e40c84666cc311a42c256bbf880db3ac99sewardj{
4637024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (VG_(clo_verbosity) >= 2) {
4638024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
4639024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu client allocs, %'10llu client frees",
4640024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__client_mallocs, stats__client_frees);
4641024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
4642024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled",
4643024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__segs_allocd, stats__segs_recycled);
4644024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_DebugMsg,
4645024598e40c84666cc311a42c256bbf880db3ac99sewardj                   "  h_:  %'10llu slow searches, %'10llu total cmps",
4646024598e40c84666cc311a42c256bbf880db3ac99sewardj                   stats__slow_searches, stats__slow_totcmps);
4647024598e40c84666cc311a42c256bbf880db3ac99sewardj
4648024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4649024598e40c84666cc311a42c256bbf880db3ac99sewardj
4650024598e40c84666cc311a42c256bbf880db3ac99sewardj   if (h_clo_lossage_check) {
4651024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
4652024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld total memory references",
4653024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__tot_mem_refs);
4654024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld   of which are in a known segment",
4655024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__refs_in_a_seg);
4656024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "%12lld   of which are 'lost' w.r.t the seg",
4657024598e40c84666cc311a42c256bbf880db3ac99sewardj                               stats__refs_lost_seg);
4658024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
4659024598e40c84666cc311a42c256bbf880db3ac99sewardj      show_lossage();
4660024598e40c84666cc311a42c256bbf880db3ac99sewardj      VG_(message)(Vg_UserMsg, "");
4661024598e40c84666cc311a42c256bbf880db3ac99sewardj   } else {
4662024598e40c84666cc311a42c256bbf880db3ac99sewardj      tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
4663024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
4664024598e40c84666cc311a42c256bbf880db3ac99sewardj}
4665024598e40c84666cc311a42c256bbf880db3ac99sewardj
4666024598e40c84666cc311a42c256bbf880db3ac99sewardj
4667024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4668024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- end                                                 h_main.c ---*/
4669024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
4670