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