h_main.c revision e6451332ee19f6d70821bf8e24781ff8868bdb3c
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 149f207460d70d38c46c9e81996a3dcdf90961c6dbnjn Copyright (C) 2003-2009 Nicholas Nethercote 15024598e40c84666cc311a42c256bbf880db3ac99sewardj njn@valgrind.org 16024598e40c84666cc311a42c256bbf880db3ac99sewardj 17024598e40c84666cc311a42c256bbf880db3ac99sewardj Valgrind-3.X port: 18024598e40c84666cc311a42c256bbf880db3ac99sewardj 199f207460d70d38c46c9e81996a3dcdf90961c6dbnjn Copyright (C) 2008-2009 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 1167024598e40c84666cc311a42c256bbf880db3ac99sewardj // Don't check code being translated -- very slow, and not much point 1168024598e40c84666cc311a42c256bbf880db3ac99sewardj if (Vg_CoreTranslate == part) return; 1169024598e40c84666cc311a42c256bbf880db3ac99sewardj 1170024598e40c84666cc311a42c256bbf880db3ac99sewardj // Don't check the signal case -- only happens in core, no need to check 1171024598e40c84666cc311a42c256bbf880db3ac99sewardj if (Vg_CoreSignal == part) return; 1172024598e40c84666cc311a42c256bbf880db3ac99sewardj 1173024598e40c84666cc311a42c256bbf880db3ac99sewardj // Only expect syscalls after this point 1174024598e40c84666cc311a42c256bbf880db3ac99sewardj if (part != Vg_CoreSysCall) { 1175024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("part = %d\n", part); 1176024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(tool_panic)("unknown corepart in pre_mem_access2"); 1177024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1178024598e40c84666cc311a42c256bbf880db3ac99sewardj 1179024598e40c84666cc311a42c256bbf880db3ac99sewardj // Check first and last bytes match 11809520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj seglo = get_Seg_containing_addr( s ); 11819520845eeeb59e9eafa5c6fb0d68b4a392e94f41sewardj seghi = get_Seg_containing_addr( e ); 1182024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert( BOTTOM != seglo && NONPTR != seglo ); 1183024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert( BOTTOM != seghi && NONPTR != seghi ); 1184024598e40c84666cc311a42c256bbf880db3ac99sewardj 11854c245e595b9f6300d3120408ca873f7115d9cc7dnjn /* record an error if start and end are in different, but known segments */ 1186024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_known_segment(seglo) && is_known_segment(seghi) 1187024598e40c84666cc311a42c256bbf880db3ac99sewardj && seglo != seghi) { 1188024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_sysparam_error(tid, part, str, s, e, seglo, seghi); 1189024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1190024598e40c84666cc311a42c256bbf880db3ac99sewardj else 1191024598e40c84666cc311a42c256bbf880db3ac99sewardj /* record an error if start is in a known segment but end isn't */ 1192024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_known_segment(seglo) && !is_known_segment(seghi)) { 1193024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN); 1194024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1195024598e40c84666cc311a42c256bbf880db3ac99sewardj else 1196024598e40c84666cc311a42c256bbf880db3ac99sewardj /* record an error if end is in a known segment but start isn't */ 1197024598e40c84666cc311a42c256bbf880db3ac99sewardj if (!is_known_segment(seglo) && is_known_segment(seghi)) { 1198024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi); 1199024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1200024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1201024598e40c84666cc311a42c256bbf880db3ac99sewardj 1202024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_access ( CorePart part, ThreadId tid, Char* s, 1203024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr base, SizeT size ) 1204024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1205024598e40c84666cc311a42c256bbf880db3ac99sewardj pre_mem_access2( part, tid, s, base, base + size - 1 ); 1206024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1207024598e40c84666cc311a42c256bbf880db3ac99sewardj 1208024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_mem_read_asciiz ( CorePart part, ThreadId tid, 1209024598e40c84666cc311a42c256bbf880db3ac99sewardj Char* s, Addr lo ) 1210024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1211024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr hi = lo; 1212024598e40c84666cc311a42c256bbf880db3ac99sewardj 1213024598e40c84666cc311a42c256bbf880db3ac99sewardj // Nb: the '\0' must be included in the lo...hi range 1214024598e40c84666cc311a42c256bbf880db3ac99sewardj while ('\0' != *(Char*)hi) hi++; 1215024598e40c84666cc311a42c256bbf880db3ac99sewardj pre_mem_access2( part, tid, s, lo, hi ); 1216024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1217024598e40c84666cc311a42c256bbf880db3ac99sewardj 1218024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_mem_write(Addr a, UInt len) 1219024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 1220024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz set_mem_unknown(a, len); 1221024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 1222024598e40c84666cc311a42c256bbf880db3ac99sewardj 1223024598e40c84666cc311a42c256bbf880db3ac99sewardj 1224024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 1225024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Register event handlers ---*/ 1226024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 1227024598e40c84666cc311a42c256bbf880db3ac99sewardj 1228024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static void post_regs_write_init ( void ) 1229024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 1230024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz UInt i; 1231024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz for (i = R_EAX; i <= R_EDI; i++) 1232024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz VG_(set_shadow_archreg)( i, (UInt)UNKNOWN ); 1233024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 1234024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz // Don't bother about eflags 1235024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 1236024598e40c84666cc311a42c256bbf880db3ac99sewardj 1237024598e40c84666cc311a42c256bbf880db3ac99sewardj// BEGIN move this uglyness to pc_machine.c 1238024598e40c84666cc311a42c256bbf880db3ac99sewardj 1239024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_big_endian ( void ) { 1240024598e40c84666cc311a42c256bbf880db3ac99sewardj UInt x = 0x11223344; 1241024598e40c84666cc311a42c256bbf880db3ac99sewardj return 0x1122 == *(UShort*)(&x); 1242024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1243024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool host_is_little_endian ( void ) { 1244024598e40c84666cc311a42c256bbf880db3ac99sewardj UInt x = 0x11223344; 1245024598e40c84666cc311a42c256bbf880db3ac99sewardj return 0x3344 == *(UShort*)(&x); 1246024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1247024598e40c84666cc311a42c256bbf880db3ac99sewardj 1248024598e40c84666cc311a42c256bbf880db3ac99sewardj#define N_INTREGINFO_OFFSETS 4 1249024598e40c84666cc311a42c256bbf880db3ac99sewardj 1250024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Holds the result of a query to 'get_IntRegInfo'. Valid values for 1251024598e40c84666cc311a42c256bbf880db3ac99sewardj n_offsets are: 1252024598e40c84666cc311a42c256bbf880db3ac99sewardj 1253024598e40c84666cc311a42c256bbf880db3ac99sewardj -1: means the queried guest state slice exactly matches 1254024598e40c84666cc311a42c256bbf880db3ac99sewardj one integer register 1255024598e40c84666cc311a42c256bbf880db3ac99sewardj 1256024598e40c84666cc311a42c256bbf880db3ac99sewardj 0: means the queried guest state slice does not overlap any 1257024598e40c84666cc311a42c256bbf880db3ac99sewardj integer registers 1258024598e40c84666cc311a42c256bbf880db3ac99sewardj 1259024598e40c84666cc311a42c256bbf880db3ac99sewardj 1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset 1260024598e40c84666cc311a42c256bbf880db3ac99sewardj overlaps n_offsets different integer registers, and their base 1261024598e40c84666cc311a42c256bbf880db3ac99sewardj offsets are placed in the offsets array. 1262024598e40c84666cc311a42c256bbf880db3ac99sewardj*/ 1263024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef 1264024598e40c84666cc311a42c256bbf880db3ac99sewardj struct { 1265024598e40c84666cc311a42c256bbf880db3ac99sewardj Int offsets[N_INTREGINFO_OFFSETS]; 1266024598e40c84666cc311a42c256bbf880db3ac99sewardj Int n_offsets; 1267024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1268024598e40c84666cc311a42c256bbf880db3ac99sewardj IntRegInfo; 1269024598e40c84666cc311a42c256bbf880db3ac99sewardj 1270024598e40c84666cc311a42c256bbf880db3ac99sewardj 1271024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_x86) 1272024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_x86.h" 1273024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State) 1274024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif 1275024598e40c84666cc311a42c256bbf880db3ac99sewardj 1276024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_amd64) 1277024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_amd64.h" 1278024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State) 1279024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO) 1280024598e40c84666cc311a42c256bbf880db3ac99sewardj# define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO) 1281024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif 1282024598e40c84666cc311a42c256bbf880db3ac99sewardj 1283024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc32) 1284024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc32.h" 1285024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State) 1286024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif 1287024598e40c84666cc311a42c256bbf880db3ac99sewardj 1288024598e40c84666cc311a42c256bbf880db3ac99sewardj#if defined(VGA_ppc64) 1289024598e40c84666cc311a42c256bbf880db3ac99sewardj# include "libvex_guest_ppc64.h" 1290024598e40c84666cc311a42c256bbf880db3ac99sewardj# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State) 1291024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif 1292024598e40c84666cc311a42c256bbf880db3ac99sewardj 1293024598e40c84666cc311a42c256bbf880db3ac99sewardj 1294024598e40c84666cc311a42c256bbf880db3ac99sewardj/* See description on definition of type IntRegInfo. */ 1295024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB ) 1296024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1297024598e40c84666cc311a42c256bbf880db3ac99sewardj /* --------------------- x86 --------------------- */ 1298024598e40c84666cc311a42c256bbf880db3ac99sewardj 1299024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(VGA_x86) 1300024598e40c84666cc311a42c256bbf880db3ac99sewardj 1301024598e40c84666cc311a42c256bbf880db3ac99sewardj# define GOF(_fieldname) \ 1302024598e40c84666cc311a42c256bbf880db3ac99sewardj (offsetof(VexGuestX86State,guest_##_fieldname)) 1303024598e40c84666cc311a42c256bbf880db3ac99sewardj 1304024598e40c84666cc311a42c256bbf880db3ac99sewardj Int o = offset; 1305024598e40c84666cc311a42c256bbf880db3ac99sewardj Int sz = szB; 1306024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is4 = sz == 4; 1307024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is21 = sz == 2 || sz == 1; 1308024598e40c84666cc311a42c256bbf880db3ac99sewardj 1309024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sz > 0); 1310024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(host_is_little_endian()); 1311024598e40c84666cc311a42c256bbf880db3ac99sewardj 1312024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Set default state to "does not intersect any int register". */ 1313024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(memset)( iii, 0, sizeof(*iii) ); 1314024598e40c84666cc311a42c256bbf880db3ac99sewardj 1315024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Exact accesses to integer registers */ 1316024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EAX) && is4) goto exactly1; 1317024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ECX) && is4) goto exactly1; 1318024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EDX) && is4) goto exactly1; 1319024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EBX) && is4) goto exactly1; 1320024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ESP) && is4) goto exactly1; 1321024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EBP) && is4) goto exactly1; 1322024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ESI) && is4) goto exactly1; 1323024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EDI) && is4) goto exactly1; 1324024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EIP) && is4) goto none; 13255685ade0e6988c118c0451c50c72a3f2533b7efesewardj if (o == GOF(IP_AT_SYSCALL) && is4) goto none; 1326024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_OP) && is4) goto none; 1327024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_DEP1) && is4) goto none; 1328024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_DEP2) && is4) goto none; 1329024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_NDEP) && is4) goto none; 1330024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(DFLAG) && is4) goto none; 1331024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(IDFLAG) && is4) goto none; 1332024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ACFLAG) && is4) goto none; 1333024598e40c84666cc311a42c256bbf880db3ac99sewardj 1334024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Partial accesses to integer registers */ 1335024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EAX) && is21) { o -= 0; goto contains_o; } 1336024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EAX)+1 && is21) { o -= 1; o -= 0; goto contains_o; } 1337024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ECX) && is21) { o -= 0; goto contains_o; } 1338024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ECX)+1 && is21) { o -= 1; o -= 0; goto contains_o; } 1339024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EBX) && is21) { o -= 0; goto contains_o; } 1340db44098732d646126c8f9168e4f05e08a4040cafsewardj if (o == GOF(EBX)+1 && is21) { o -= 1; o -= 0; goto contains_o; } 1341024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EDX) && is21) { o -= 0; goto contains_o; } 1342024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EDX)+1 && is21) { o -= 1; o -= 0; goto contains_o; } 1343024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(ESI) && is21) { o -= 0; goto contains_o; } 1344024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EDI) && is21) { o -= 0; goto contains_o; } 1345024598e40c84666cc311a42c256bbf880db3ac99sewardj 1346024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Segment related guff */ 1347024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GS) && sz == 2) goto none; 1348024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(LDT) && is4) goto none; 1349024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GDT) && is4) goto none; 1350024598e40c84666cc311a42c256bbf880db3ac99sewardj 1351024598e40c84666cc311a42c256bbf880db3ac99sewardj /* FP admin related */ 1352024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(SSEROUND) && is4) goto none; 1353024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPROUND) && is4) goto none; 1354024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EMWARN) && is4) goto none; 1355024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FTOP) && is4) goto none; 1356024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPTAG) && sz == 8) goto none; 1357024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FC3210) && is4) goto none; 1358024598e40c84666cc311a42c256bbf880db3ac99sewardj 1359024598e40c84666cc311a42c256bbf880db3ac99sewardj /* xmm registers, including arbitrary sub-parts */ 1360024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none; 1361024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none; 1362024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none; 1363024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none; 1364024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none; 1365024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none; 1366024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none; 1367024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none; 1368024598e40c84666cc311a42c256bbf880db3ac99sewardj 1369024598e40c84666cc311a42c256bbf880db3ac99sewardj /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked 1370024598e40c84666cc311a42c256bbf880db3ac99sewardj to be exactly equal to one of FPREG[0] .. FPREG[7]) */ 1371024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none; 1372024598e40c84666cc311a42c256bbf880db3ac99sewardj 1373024598e40c84666cc311a42c256bbf880db3ac99sewardj /* the entire mmx/x87 register bank in one big piece */ 1374024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPREG) && sz == 64) goto none; 1375024598e40c84666cc311a42c256bbf880db3ac99sewardj 1376024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz); 1377024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1378024598e40c84666cc311a42c256bbf880db3ac99sewardj# undef GOF 1379024598e40c84666cc311a42c256bbf880db3ac99sewardj 1380024598e40c84666cc311a42c256bbf880db3ac99sewardj /* -------------------- amd64 -------------------- */ 1381024598e40c84666cc311a42c256bbf880db3ac99sewardj 1382024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_amd64) 1383024598e40c84666cc311a42c256bbf880db3ac99sewardj 1384024598e40c84666cc311a42c256bbf880db3ac99sewardj# define GOF(_fieldname) \ 1385024598e40c84666cc311a42c256bbf880db3ac99sewardj (offsetof(VexGuestAMD64State,guest_##_fieldname)) 1386024598e40c84666cc311a42c256bbf880db3ac99sewardj 1387024598e40c84666cc311a42c256bbf880db3ac99sewardj Int o = offset; 1388024598e40c84666cc311a42c256bbf880db3ac99sewardj Int sz = szB; 1389024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is421 = sz == 4 || sz == 2 || sz == 1; 1390024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is8 = sz == 8; 1391024598e40c84666cc311a42c256bbf880db3ac99sewardj 1392024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sz > 0); 1393024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(host_is_little_endian()); 1394024598e40c84666cc311a42c256bbf880db3ac99sewardj 1395024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Set default state to "does not intersect any int register". */ 1396024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(memset)( iii, 0, sizeof(*iii) ); 1397024598e40c84666cc311a42c256bbf880db3ac99sewardj 1398024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Exact accesses to integer registers */ 1399024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RAX) && is8) goto exactly1; 1400024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RCX) && is8) goto exactly1; 1401024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RDX) && is8) goto exactly1; 1402024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RBX) && is8) goto exactly1; 1403024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RSP) && is8) goto exactly1; 1404024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RBP) && is8) goto exactly1; 1405024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RSI) && is8) goto exactly1; 1406024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RDI) && is8) goto exactly1; 1407024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R8) && is8) goto exactly1; 1408024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R9) && is8) goto exactly1; 1409024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R10) && is8) goto exactly1; 1410024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R11) && is8) goto exactly1; 1411024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R12) && is8) goto exactly1; 1412024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R13) && is8) goto exactly1; 1413024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R14) && is8) goto exactly1; 1414024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R15) && is8) goto exactly1; 1415024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RIP) && is8) goto exactly1; 14165685ade0e6988c118c0451c50c72a3f2533b7efesewardj if (o == GOF(IP_AT_SYSCALL) && is8) goto none; 1417024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_OP) && is8) goto none; 1418024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_DEP1) && is8) goto none; 1419024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_DEP2) && is8) goto none; 1420024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CC_NDEP) && is8) goto none; 1421024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(DFLAG) && is8) goto none; 1422024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(IDFLAG) && is8) goto none; 1423024598e40c84666cc311a42c256bbf880db3ac99sewardj 1424024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Partial accesses to integer registers */ 1425024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RAX) && is421) { o -= 0; goto contains_o; } 1426024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RAX)+1 && is421) { o -= 1; o -= 0; goto contains_o; } 1427024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RCX) && is421) { o -= 0; goto contains_o; } 1428024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RCX)+1 && is421) { o -= 1; o -= 0; goto contains_o; } 1429024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RDX) && is421) { o -= 0; goto contains_o; } 1430024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RDX)+1 && is421) { o -= 1; o -= 0; goto contains_o; } 1431024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RBX) && is421) { o -= 0; goto contains_o; } 1432024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RBX)+1 && is421) { o -= 1; o -= 0; goto contains_o; } 1433024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RBP) && is421) { o -= 0; goto contains_o; } 1434024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RSI) && is421) { o -= 0; goto contains_o; } 1435024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(RDI) && is421) { o -= 0; goto contains_o; } 1436024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R8) && is421) { o -= 0; goto contains_o; } 1437024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R9) && is421) { o -= 0; goto contains_o; } 1438024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R10) && is421) { o -= 0; goto contains_o; } 1439024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R11) && is421) { o -= 0; goto contains_o; } 1440024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R12) && is421) { o -= 0; goto contains_o; } 1441024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R13) && is421) { o -= 0; goto contains_o; } 1442024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R14) && is421) { o -= 0; goto contains_o; } 1443024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(R15) && is421) { o -= 0; goto contains_o; } 1444024598e40c84666cc311a42c256bbf880db3ac99sewardj 1445024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Segment related guff */ 1446024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FS_ZERO) && is8) goto exactly1; 1447024598e40c84666cc311a42c256bbf880db3ac99sewardj 1448024598e40c84666cc311a42c256bbf880db3ac99sewardj /* FP admin related */ 1449024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(SSEROUND) && is8) goto none; 1450024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPROUND) && is8) goto none; 1451024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EMWARN) && sz == 4) goto none; 1452024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FTOP) && sz == 4) goto none; 1453024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPTAG) && is8) goto none; 1454024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FC3210) && is8) goto none; 1455024598e40c84666cc311a42c256bbf880db3ac99sewardj 1456024598e40c84666cc311a42c256bbf880db3ac99sewardj /* xmm registers, including arbitrary sub-parts */ 1457024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none; 1458024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none; 1459024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none; 1460024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none; 1461024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none; 1462024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none; 1463024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none; 1464024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none; 1465024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM8) && o+sz <= GOF(XMM8)+16) goto none; 1466024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM9) && o+sz <= GOF(XMM9)+16) goto none; 1467024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none; 1468024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none; 1469024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none; 1470024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none; 1471024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none; 1472024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none; 1473024598e40c84666cc311a42c256bbf880db3ac99sewardj 1474024598e40c84666cc311a42c256bbf880db3ac99sewardj /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked 1475024598e40c84666cc311a42c256bbf880db3ac99sewardj to be exactly equal to one of FPREG[0] .. FPREG[7]) */ 1476024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none; 1477024598e40c84666cc311a42c256bbf880db3ac99sewardj 1478024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz); 1479024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1480024598e40c84666cc311a42c256bbf880db3ac99sewardj# undef GOF 1481024598e40c84666cc311a42c256bbf880db3ac99sewardj 1482024598e40c84666cc311a42c256bbf880db3ac99sewardj /* -------------------- ppc32 -------------------- */ 1483024598e40c84666cc311a42c256bbf880db3ac99sewardj 1484024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_ppc32) 1485024598e40c84666cc311a42c256bbf880db3ac99sewardj 1486024598e40c84666cc311a42c256bbf880db3ac99sewardj# define GOF(_fieldname) \ 1487024598e40c84666cc311a42c256bbf880db3ac99sewardj (offsetof(VexGuestPPC32State,guest_##_fieldname)) 1488024598e40c84666cc311a42c256bbf880db3ac99sewardj 1489024598e40c84666cc311a42c256bbf880db3ac99sewardj Int o = offset; 1490024598e40c84666cc311a42c256bbf880db3ac99sewardj Int sz = szB; 1491024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is4 = sz == 4; 1492024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is8 = sz == 8; 1493024598e40c84666cc311a42c256bbf880db3ac99sewardj 1494024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sz > 0); 1495024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(host_is_big_endian()); 1496024598e40c84666cc311a42c256bbf880db3ac99sewardj 1497024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Set default state to "does not intersect any int register". */ 1498024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(memset)( iii, 0, sizeof(*iii) ); 1499024598e40c84666cc311a42c256bbf880db3ac99sewardj 1500024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Exact accesses to integer registers */ 1501024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR0) && is4) goto exactly1; 1502024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR1) && is4) goto exactly1; 1503024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR2) && is4) goto exactly1; 1504024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR3) && is4) goto exactly1; 1505024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR4) && is4) goto exactly1; 1506024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR5) && is4) goto exactly1; 1507024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR6) && is4) goto exactly1; 1508024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR7) && is4) goto exactly1; 1509024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR8) && is4) goto exactly1; 1510024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR9) && is4) goto exactly1; 1511024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR10) && is4) goto exactly1; 1512024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR11) && is4) goto exactly1; 1513024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR12) && is4) goto exactly1; 1514024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR13) && is4) goto exactly1; 1515024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR14) && is4) goto exactly1; 1516024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR15) && is4) goto exactly1; 1517024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR16) && is4) goto exactly1; 1518024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR17) && is4) goto exactly1; 1519024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR18) && is4) goto exactly1; 1520024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR19) && is4) goto exactly1; 1521024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR20) && is4) goto exactly1; 1522024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR21) && is4) goto exactly1; 1523024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR22) && is4) goto exactly1; 1524024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR23) && is4) goto exactly1; 1525024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR24) && is4) goto exactly1; 1526024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR25) && is4) goto exactly1; 1527024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR26) && is4) goto exactly1; 1528024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR27) && is4) goto exactly1; 1529024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR28) && is4) goto exactly1; 1530024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR29) && is4) goto exactly1; 1531024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR30) && is4) goto exactly1; 1532024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR31) && is4) goto exactly1; 1533024598e40c84666cc311a42c256bbf880db3ac99sewardj 1534024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Misc integer reg and condition code accesses */ 1535024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(LR) && is4) goto exactly1; 1536024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CTR) && is4) goto exactly1; 1537024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CIA) && is4) goto none; 153890fc9d77441966837004dc5a9b2b97c435cdb105sewardj if (o == GOF(IP_AT_SYSCALL) && is4) goto none; 1539024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(TISTART) && is4) goto none; 1540024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(TILEN) && is4) goto none; 1541024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(REDIR_SP) && is4) goto none; 1542024598e40c84666cc311a42c256bbf880db3ac99sewardj 1543024598e40c84666cc311a42c256bbf880db3ac99sewardj if (sz == 1) { 1544024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_SO)) goto none; 1545024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_OV)) goto none; 1546024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_CA)) goto none; 1547024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_BC)) goto none; 1548024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR0_321)) goto none; 1549024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR0_0)) goto none; 1550024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR1_321)) goto none; 1551024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR1_0)) goto none; 1552024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR2_321)) goto none; 1553024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR2_0)) goto none; 1554024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR3_321)) goto none; 1555024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR3_0)) goto none; 1556024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR4_321)) goto none; 1557024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR4_0)) goto none; 1558024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR5_321)) goto none; 1559024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR5_0)) goto none; 1560024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR6_321)) goto none; 1561024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR6_0)) goto none; 1562024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR7_321)) goto none; 1563024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR7_0)) goto none; 1564024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1565024598e40c84666cc311a42c256bbf880db3ac99sewardj 1566024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Exact accesses to FP registers */ 1567024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR0) && is8) goto none; 1568024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR1) && is8) goto none; 1569024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR2) && is8) goto none; 1570024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR3) && is8) goto none; 1571024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR4) && is8) goto none; 1572024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR5) && is8) goto none; 1573024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR6) && is8) goto none; 1574024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR7) && is8) goto none; 1575024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR8) && is8) goto none; 1576024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR9) && is8) goto none; 1577024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR10) && is8) goto none; 1578024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR11) && is8) goto none; 1579024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR12) && is8) goto none; 1580024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR13) && is8) goto none; 1581024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR14) && is8) goto none; 1582024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR15) && is8) goto none; 1583024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR16) && is8) goto none; 1584024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR17) && is8) goto none; 1585024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR18) && is8) goto none; 1586024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR19) && is8) goto none; 1587024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR20) && is8) goto none; 1588024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR21) && is8) goto none; 1589024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR22) && is8) goto none; 1590024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR23) && is8) goto none; 1591024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR24) && is8) goto none; 1592024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR25) && is8) goto none; 1593024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR26) && is8) goto none; 1594024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR27) && is8) goto none; 1595024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR28) && is8) goto none; 1596024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR29) && is8) goto none; 1597024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR30) && is8) goto none; 1598024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR31) && is8) goto none; 1599024598e40c84666cc311a42c256bbf880db3ac99sewardj 1600024598e40c84666cc311a42c256bbf880db3ac99sewardj /* FP admin related */ 1601024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPROUND) && is4) goto none; 1602024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EMWARN) && is4) goto none; 1603024598e40c84666cc311a42c256bbf880db3ac99sewardj 1604024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Altivec registers */ 1605024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR0) && sz == 16) goto none; 1606024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR1) && sz == 16) goto none; 1607024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR2) && sz == 16) goto none; 1608024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR3) && sz == 16) goto none; 1609024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR4) && sz == 16) goto none; 1610024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR5) && sz == 16) goto none; 1611024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR6) && sz == 16) goto none; 1612024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR7) && sz == 16) goto none; 1613024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR8) && sz == 16) goto none; 1614024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR9) && sz == 16) goto none; 1615024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR10) && sz == 16) goto none; 1616024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR11) && sz == 16) goto none; 1617024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR12) && sz == 16) goto none; 1618024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR13) && sz == 16) goto none; 1619024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR14) && sz == 16) goto none; 1620024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR15) && sz == 16) goto none; 1621024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR16) && sz == 16) goto none; 1622024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR17) && sz == 16) goto none; 1623024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR18) && sz == 16) goto none; 1624024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR19) && sz == 16) goto none; 1625024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR20) && sz == 16) goto none; 1626024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR21) && sz == 16) goto none; 1627024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR22) && sz == 16) goto none; 1628024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR23) && sz == 16) goto none; 1629024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR24) && sz == 16) goto none; 1630024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR25) && sz == 16) goto none; 1631024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR26) && sz == 16) goto none; 1632024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR27) && sz == 16) goto none; 1633024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR28) && sz == 16) goto none; 1634024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR29) && sz == 16) goto none; 1635024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR30) && sz == 16) goto none; 1636024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR31) && sz == 16) goto none; 1637024598e40c84666cc311a42c256bbf880db3ac99sewardj 1638aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj /* Altivec admin related */ 1639aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj if (o == GOF(VRSAVE) && is4) goto none; 1640aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj 1641024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz); 1642024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1643024598e40c84666cc311a42c256bbf880db3ac99sewardj# undef GOF 1644024598e40c84666cc311a42c256bbf880db3ac99sewardj 1645024598e40c84666cc311a42c256bbf880db3ac99sewardj /* -------------------- ppc64 -------------------- */ 1646024598e40c84666cc311a42c256bbf880db3ac99sewardj 1647024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_ppc64) 1648024598e40c84666cc311a42c256bbf880db3ac99sewardj 1649024598e40c84666cc311a42c256bbf880db3ac99sewardj# define GOF(_fieldname) \ 1650024598e40c84666cc311a42c256bbf880db3ac99sewardj (offsetof(VexGuestPPC64State,guest_##_fieldname)) 1651024598e40c84666cc311a42c256bbf880db3ac99sewardj 1652024598e40c84666cc311a42c256bbf880db3ac99sewardj Int o = offset; 1653024598e40c84666cc311a42c256bbf880db3ac99sewardj Int sz = szB; 1654024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is4 = sz == 4; 1655024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is8 = sz == 8; 1656024598e40c84666cc311a42c256bbf880db3ac99sewardj 1657024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sz > 0); 1658024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(host_is_big_endian()); 1659024598e40c84666cc311a42c256bbf880db3ac99sewardj 1660024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Set default state to "does not intersect any int register". */ 1661024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(memset)( iii, 0, sizeof(*iii) ); 1662024598e40c84666cc311a42c256bbf880db3ac99sewardj 1663024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Exact accesses to integer registers */ 1664024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR0) && is8) goto exactly1; 1665024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR1) && is8) goto exactly1; 1666024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR2) && is8) goto exactly1; 1667024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR3) && is8) goto exactly1; 1668024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR4) && is8) goto exactly1; 1669024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR5) && is8) goto exactly1; 1670024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR6) && is8) goto exactly1; 1671024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR7) && is8) goto exactly1; 1672024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR8) && is8) goto exactly1; 1673024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR9) && is8) goto exactly1; 1674024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR10) && is8) goto exactly1; 1675024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR11) && is8) goto exactly1; 1676024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR12) && is8) goto exactly1; 1677024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR13) && is8) goto exactly1; 1678024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR14) && is8) goto exactly1; 1679024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR15) && is8) goto exactly1; 1680024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR16) && is8) goto exactly1; 1681024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR17) && is8) goto exactly1; 1682024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR18) && is8) goto exactly1; 1683024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR19) && is8) goto exactly1; 1684024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR20) && is8) goto exactly1; 1685024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR21) && is8) goto exactly1; 1686024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR22) && is8) goto exactly1; 1687024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR23) && is8) goto exactly1; 1688024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR24) && is8) goto exactly1; 1689024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR25) && is8) goto exactly1; 1690024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR26) && is8) goto exactly1; 1691024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR27) && is8) goto exactly1; 1692024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR28) && is8) goto exactly1; 1693024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR29) && is8) goto exactly1; 1694024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR30) && is8) goto exactly1; 1695024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(GPR31) && is8) goto exactly1; 1696024598e40c84666cc311a42c256bbf880db3ac99sewardj 1697024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Misc integer reg and condition code accesses */ 1698024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(LR) && is8) goto exactly1; 1699024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CTR) && is8) goto exactly1; 1700024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CIA) && is8) goto none; 170190fc9d77441966837004dc5a9b2b97c435cdb105sewardj if (o == GOF(IP_AT_SYSCALL) && is8) goto none; 1702024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(TISTART) && is8) goto none; 1703024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(TILEN) && is8) goto none; 1704024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(REDIR_SP) && is8) goto none; 1705024598e40c84666cc311a42c256bbf880db3ac99sewardj 1706024598e40c84666cc311a42c256bbf880db3ac99sewardj if (sz == 1) { 1707024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_SO)) goto none; 1708024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_OV)) goto none; 1709024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_CA)) goto none; 1710024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(XER_BC)) goto none; 1711024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR0_321)) goto none; 1712024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR0_0)) goto none; 1713024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR1_321)) goto none; 1714024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR1_0)) goto none; 1715024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR2_321)) goto none; 1716024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR2_0)) goto none; 1717024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR3_321)) goto none; 1718024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR3_0)) goto none; 1719024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR4_321)) goto none; 1720024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR4_0)) goto none; 1721024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR5_321)) goto none; 1722024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR5_0)) goto none; 1723024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR6_321)) goto none; 1724024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR6_0)) goto none; 1725024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR7_321)) goto none; 1726024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(CR7_0)) goto none; 1727024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1728024598e40c84666cc311a42c256bbf880db3ac99sewardj 1729024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Exact accesses to FP registers */ 1730024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR0) && is8) goto none; 1731024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR1) && is8) goto none; 1732024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR2) && is8) goto none; 1733024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR3) && is8) goto none; 1734024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR4) && is8) goto none; 1735024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR5) && is8) goto none; 1736024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR6) && is8) goto none; 1737024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR7) && is8) goto none; 1738024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR8) && is8) goto none; 1739024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR9) && is8) goto none; 1740024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR10) && is8) goto none; 1741024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR11) && is8) goto none; 1742024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR12) && is8) goto none; 1743024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR13) && is8) goto none; 1744024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR14) && is8) goto none; 1745024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR15) && is8) goto none; 1746024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR16) && is8) goto none; 1747024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR17) && is8) goto none; 1748024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR18) && is8) goto none; 1749024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR19) && is8) goto none; 1750024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR20) && is8) goto none; 1751024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR21) && is8) goto none; 1752024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR22) && is8) goto none; 1753024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR23) && is8) goto none; 1754024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR24) && is8) goto none; 1755024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR25) && is8) goto none; 1756024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR26) && is8) goto none; 1757024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR27) && is8) goto none; 1758024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR28) && is8) goto none; 1759024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR29) && is8) goto none; 1760024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR30) && is8) goto none; 1761024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPR31) && is8) goto none; 1762024598e40c84666cc311a42c256bbf880db3ac99sewardj 1763024598e40c84666cc311a42c256bbf880db3ac99sewardj /* FP admin related */ 1764024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(FPROUND) && is4) goto none; 1765024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(EMWARN) && is4) goto none; 1766024598e40c84666cc311a42c256bbf880db3ac99sewardj 1767024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Altivec registers */ 1768024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR0) && sz == 16) goto none; 1769024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR1) && sz == 16) goto none; 1770024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR2) && sz == 16) goto none; 1771024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR3) && sz == 16) goto none; 1772024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR4) && sz == 16) goto none; 1773024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR5) && sz == 16) goto none; 1774024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR6) && sz == 16) goto none; 1775024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR7) && sz == 16) goto none; 1776024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR8) && sz == 16) goto none; 1777024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR9) && sz == 16) goto none; 1778024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR10) && sz == 16) goto none; 1779024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR11) && sz == 16) goto none; 1780024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR12) && sz == 16) goto none; 1781024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR13) && sz == 16) goto none; 1782024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR14) && sz == 16) goto none; 1783024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR15) && sz == 16) goto none; 1784024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR16) && sz == 16) goto none; 1785024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR17) && sz == 16) goto none; 1786024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR18) && sz == 16) goto none; 1787024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR19) && sz == 16) goto none; 1788024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR20) && sz == 16) goto none; 1789024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR21) && sz == 16) goto none; 1790024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR22) && sz == 16) goto none; 1791024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR23) && sz == 16) goto none; 1792024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR24) && sz == 16) goto none; 1793024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR25) && sz == 16) goto none; 1794024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR26) && sz == 16) goto none; 1795024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR27) && sz == 16) goto none; 1796024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR28) && sz == 16) goto none; 1797024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR29) && sz == 16) goto none; 1798024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR30) && sz == 16) goto none; 1799024598e40c84666cc311a42c256bbf880db3ac99sewardj if (o == GOF(VR31) && sz == 16) goto none; 1800024598e40c84666cc311a42c256bbf880db3ac99sewardj 1801aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj /* Altivec admin related */ 1802aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj if (o == GOF(VRSAVE) && is4) goto none; 1803aae8208d82b8dd2b3d39daa02c8db17e0fab5ad6sewardj 1804024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz); 1805024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1806024598e40c84666cc311a42c256bbf880db3ac99sewardj# undef GOF 1807024598e40c84666cc311a42c256bbf880db3ac99sewardj 1808024598e40c84666cc311a42c256bbf880db3ac99sewardj 1809024598e40c84666cc311a42c256bbf880db3ac99sewardj# else 1810024598e40c84666cc311a42c256bbf880db3ac99sewardj# error "FIXME: not implemented for this architecture" 1811024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 1812024598e40c84666cc311a42c256bbf880db3ac99sewardj 1813024598e40c84666cc311a42c256bbf880db3ac99sewardj exactly1: 1814024598e40c84666cc311a42c256bbf880db3ac99sewardj iii->n_offsets = -1; 1815024598e40c84666cc311a42c256bbf880db3ac99sewardj return; 1816024598e40c84666cc311a42c256bbf880db3ac99sewardj none: 1817024598e40c84666cc311a42c256bbf880db3ac99sewardj iii->n_offsets = 0; 1818024598e40c84666cc311a42c256bbf880db3ac99sewardj return; 1819024598e40c84666cc311a42c256bbf880db3ac99sewardj contains_o: 1820024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(o >= 0 && 0 == (o % sizeof(UWord))); 1821024598e40c84666cc311a42c256bbf880db3ac99sewardj iii->n_offsets = 1; 1822024598e40c84666cc311a42c256bbf880db3ac99sewardj iii->offsets[0] = o; 1823024598e40c84666cc311a42c256bbf880db3ac99sewardj return; 1824024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1825024598e40c84666cc311a42c256bbf880db3ac99sewardj 1826024598e40c84666cc311a42c256bbf880db3ac99sewardj 1827024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Does 'arr' describe an indexed guest state section containing host 1828024598e40c84666cc311a42c256bbf880db3ac99sewardj words, that we want to shadow? */ 1829024598e40c84666cc311a42c256bbf880db3ac99sewardj 1830024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg_array ( IRRegArray* arr ) 1831024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1832024598e40c84666cc311a42c256bbf880db3ac99sewardj /* --------------------- x86 --------------------- */ 1833024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(VGA_x86) 1834024598e40c84666cc311a42c256bbf880db3ac99sewardj /* The x87 tag array. */ 1835024598e40c84666cc311a42c256bbf880db3ac99sewardj if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0]) 1836024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->elemTy == Ity_I8 && arr->nElems == 8) 1837024598e40c84666cc311a42c256bbf880db3ac99sewardj return False; 1838024598e40c84666cc311a42c256bbf880db3ac99sewardj /* The x87 register array. */ 1839024598e40c84666cc311a42c256bbf880db3ac99sewardj if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0]) 1840024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->elemTy == Ity_F64 && arr->nElems == 8) 1841024598e40c84666cc311a42c256bbf880db3ac99sewardj return False; 1842024598e40c84666cc311a42c256bbf880db3ac99sewardj 1843024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("is_integer_guest_reg_array(x86): unhandled: "); 1844024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRRegArray(arr); 1845024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("\n"); 1846024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1847024598e40c84666cc311a42c256bbf880db3ac99sewardj 1848024598e40c84666cc311a42c256bbf880db3ac99sewardj /* -------------------- amd64 -------------------- */ 1849024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_amd64) 1850024598e40c84666cc311a42c256bbf880db3ac99sewardj /* The x87 tag array. */ 1851024598e40c84666cc311a42c256bbf880db3ac99sewardj if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0]) 1852024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->elemTy == Ity_I8 && arr->nElems == 8) 1853024598e40c84666cc311a42c256bbf880db3ac99sewardj return False; 1854024598e40c84666cc311a42c256bbf880db3ac99sewardj /* The x87 register array. */ 1855024598e40c84666cc311a42c256bbf880db3ac99sewardj if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0]) 1856024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->elemTy == Ity_F64 && arr->nElems == 8) 1857024598e40c84666cc311a42c256bbf880db3ac99sewardj return False; 1858024598e40c84666cc311a42c256bbf880db3ac99sewardj 1859024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: "); 1860024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRRegArray(arr); 1861024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("\n"); 1862024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1863024598e40c84666cc311a42c256bbf880db3ac99sewardj 1864024598e40c84666cc311a42c256bbf880db3ac99sewardj /* -------------------- ppc32 -------------------- */ 1865024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_ppc32) 1866024598e40c84666cc311a42c256bbf880db3ac99sewardj /* The redir stack. */ 1867024598e40c84666cc311a42c256bbf880db3ac99sewardj if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0]) 1868024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->elemTy == Ity_I32 1869024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE) 1870024598e40c84666cc311a42c256bbf880db3ac99sewardj return True; 1871024598e40c84666cc311a42c256bbf880db3ac99sewardj 1872024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: "); 1873024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRRegArray(arr); 1874024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("\n"); 1875024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1876024598e40c84666cc311a42c256bbf880db3ac99sewardj 1877024598e40c84666cc311a42c256bbf880db3ac99sewardj /* -------------------- ppc64 -------------------- */ 1878024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_ppc64) 1879024598e40c84666cc311a42c256bbf880db3ac99sewardj /* The redir stack. */ 1880024598e40c84666cc311a42c256bbf880db3ac99sewardj if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0]) 1881024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->elemTy == Ity_I64 1882024598e40c84666cc311a42c256bbf880db3ac99sewardj && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE) 1883024598e40c84666cc311a42c256bbf880db3ac99sewardj return True; 1884024598e40c84666cc311a42c256bbf880db3ac99sewardj 1885024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: "); 1886024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRRegArray(arr); 1887024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("\n"); 1888024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1889024598e40c84666cc311a42c256bbf880db3ac99sewardj 1890024598e40c84666cc311a42c256bbf880db3ac99sewardj# else 1891024598e40c84666cc311a42c256bbf880db3ac99sewardj# error "FIXME: not implemented for this architecture" 1892024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 1893024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1894024598e40c84666cc311a42c256bbf880db3ac99sewardj 1895024598e40c84666cc311a42c256bbf880db3ac99sewardj 1896024598e40c84666cc311a42c256bbf880db3ac99sewardj// END move this uglyness to pc_machine.c 1897024598e40c84666cc311a42c256bbf880db3ac99sewardj 1898024598e40c84666cc311a42c256bbf880db3ac99sewardj/* returns True iff given slice exactly matches an int reg. Merely 1899024598e40c84666cc311a42c256bbf880db3ac99sewardj a convenience wrapper around get_IntRegInfo. */ 1900024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Bool is_integer_guest_reg ( Int offset, Int szB ) 1901024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1902024598e40c84666cc311a42c256bbf880db3ac99sewardj IntRegInfo iii; 1903024598e40c84666cc311a42c256bbf880db3ac99sewardj get_IntRegInfo( &iii, offset, szB ); 1904024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS); 1905024598e40c84666cc311a42c256bbf880db3ac99sewardj return iii.n_offsets == -1; 1906024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1907024598e40c84666cc311a42c256bbf880db3ac99sewardj 1908024598e40c84666cc311a42c256bbf880db3ac99sewardj/* these assume guest and host have the same endianness and 1909024598e40c84666cc311a42c256bbf880db3ac99sewardj word size (probably). */ 1910024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UWord get_guest_intreg ( ThreadId tid, Int shadowNo, 1911c4431bfe04c7490ea2d74939d222d87f13f30960njn PtrdiffT offset, SizeT size ) 1912024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1913024598e40c84666cc311a42c256bbf880db3ac99sewardj UChar tmp[ 2 + sizeof(UWord) ]; 1914024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(size == sizeof(UWord)); 1915024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0 == (offset % sizeof(UWord))); 1916024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(memset)(tmp, 0, sizeof(tmp)); 1917024598e40c84666cc311a42c256bbf880db3ac99sewardj tmp[0] = 0x31; 1918024598e40c84666cc311a42c256bbf880db3ac99sewardj tmp[ sizeof(tmp)-1 ] = 0x27; 1919024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size); 1920024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(tmp[0] == 0x31); 1921024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27); 1922024598e40c84666cc311a42c256bbf880db3ac99sewardj return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */ 1923024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1924024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void put_guest_intreg ( ThreadId tid, Int shadowNo, 1925c4431bfe04c7490ea2d74939d222d87f13f30960njn PtrdiffT offset, SizeT size, UWord w ) 1926024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1927024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(size == sizeof(UWord)); 1928024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0 == (offset % sizeof(UWord))); 1929024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(set_shadow_regs_area)(tid, shadowNo, offset, size, 1930024598e40c84666cc311a42c256bbf880db3ac99sewardj (const UChar*)&w); 1931024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1932024598e40c84666cc311a42c256bbf880db3ac99sewardj 1933024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Initialise the integer shadow registers to UNKNOWN. This is a bit 1934024598e40c84666cc311a42c256bbf880db3ac99sewardj of a nasty kludge, but it does mean we don't need to know which 1935024598e40c84666cc311a42c256bbf880db3ac99sewardj registers we really need to initialise -- simply assume that all 1936024598e40c84666cc311a42c256bbf880db3ac99sewardj integer registers will be naturally aligned w.r.t. the start of the 1937024598e40c84666cc311a42c256bbf880db3ac99sewardj guest state, and fill in all possible entries. */ 1938024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_shadow_registers ( ThreadId tid ) 1939024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1940024598e40c84666cc311a42c256bbf880db3ac99sewardj Int i, wordSzB = sizeof(UWord); 1941024598e40c84666cc311a42c256bbf880db3ac99sewardj for (i = 0; i < MC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) { 1942024598e40c84666cc311a42c256bbf880db3ac99sewardj put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN ); 1943024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1944024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1945024598e40c84666cc311a42c256bbf880db3ac99sewardj 1946c4431bfe04c7490ea2d74939d222d87f13f30960njnstatic void post_reg_write_nonptr ( ThreadId tid, PtrdiffT offset, SizeT size ) 1947024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1948024598e40c84666cc311a42c256bbf880db3ac99sewardj // syscall_return: Default is non-pointer. If it really is a pointer 1949024598e40c84666cc311a42c256bbf880db3ac99sewardj // (eg. for mmap()), SK_(post_syscall) sets it again afterwards. 1950024598e40c84666cc311a42c256bbf880db3ac99sewardj // 1951024598e40c84666cc311a42c256bbf880db3ac99sewardj // clientreq_return: All the global client requests return non-pointers 1952024598e40c84666cc311a42c256bbf880db3ac99sewardj // (except possibly CLIENT_CALL[0123], but they're handled by 1953024598e40c84666cc311a42c256bbf880db3ac99sewardj // post_reg_write_clientcall, not here). 1954024598e40c84666cc311a42c256bbf880db3ac99sewardj // 1955024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_integer_guest_reg( (Int)offset, (Int)size )) { 1956024598e40c84666cc311a42c256bbf880db3ac99sewardj put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR ); 1957024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 1958f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: on Darwin, this assertion fails because we currently do a 1959f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // 'post_reg_write' on the 'guest_CC_DEP1' pseudo-register. 1960024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1961024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1962024598e40c84666cc311a42c256bbf880db3ac99sewardj // VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR ); 1963024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1964024598e40c84666cc311a42c256bbf880db3ac99sewardj 1965024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void post_reg_write_nonptr_or_unknown ( ThreadId tid, 1966c4431bfe04c7490ea2d74939d222d87f13f30960njn PtrdiffT offset, SizeT size ) 1967024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1968024598e40c84666cc311a42c256bbf880db3ac99sewardj // deliver_signal: called from two places; one sets the reg to zero, the 1969024598e40c84666cc311a42c256bbf880db3ac99sewardj // other sets the stack pointer. 1970024598e40c84666cc311a42c256bbf880db3ac99sewardj // 1971024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_integer_guest_reg( (Int)offset, (Int)size )) { 1972024598e40c84666cc311a42c256bbf880db3ac99sewardj put_guest_intreg( 1973024598e40c84666cc311a42c256bbf880db3ac99sewardj tid, 1/*shadowno*/, offset, size, 1974024598e40c84666cc311a42c256bbf880db3ac99sewardj (UWord)nonptr_or_unknown( 1975024598e40c84666cc311a42c256bbf880db3ac99sewardj get_guest_intreg( tid, 0/*shadowno*/, 1976024598e40c84666cc311a42c256bbf880db3ac99sewardj offset, size ))); 1977024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 1978024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 1979024598e40c84666cc311a42c256bbf880db3ac99sewardj } 1980024598e40c84666cc311a42c256bbf880db3ac99sewardj} 1981024598e40c84666cc311a42c256bbf880db3ac99sewardj 1982024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_reg_write_demux ( CorePart part, ThreadId tid, 1983c4431bfe04c7490ea2d74939d222d87f13f30960njn PtrdiffT guest_state_offset, SizeT size) 1984024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 1985024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0) 1986024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n", 1987024598e40c84666cc311a42c256bbf880db3ac99sewardj (Int)tid, (Int)part, 1988024598e40c84666cc311a42c256bbf880db3ac99sewardj guest_state_offset, size); 1989024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (part) { 1990024598e40c84666cc311a42c256bbf880db3ac99sewardj case Vg_CoreStartup: 1991024598e40c84666cc311a42c256bbf880db3ac99sewardj /* This is a bit of a kludge since for any Vg_CoreStartup 1992024598e40c84666cc311a42c256bbf880db3ac99sewardj event we overwrite the entire shadow register set. But 1993024598e40c84666cc311a42c256bbf880db3ac99sewardj that's ok - we're only called once with 1994024598e40c84666cc311a42c256bbf880db3ac99sewardj part==Vg_CoreStartup event, and in that case the supplied 1995024598e40c84666cc311a42c256bbf880db3ac99sewardj offset & size cover the entire guest state anyway. */ 1996024598e40c84666cc311a42c256bbf880db3ac99sewardj init_shadow_registers(tid); 1997024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 1998024598e40c84666cc311a42c256bbf880db3ac99sewardj case Vg_CoreSysCall: 1999024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0) VG_(printf)("ZZZZZZZ p_r_w -> NONPTR\n"); 2000024598e40c84666cc311a42c256bbf880db3ac99sewardj post_reg_write_nonptr( tid, guest_state_offset, size ); 2001024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 2002024598e40c84666cc311a42c256bbf880db3ac99sewardj case Vg_CoreClientReq: 2003024598e40c84666cc311a42c256bbf880db3ac99sewardj post_reg_write_nonptr( tid, guest_state_offset, size ); 2004024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 2005024598e40c84666cc311a42c256bbf880db3ac99sewardj case Vg_CoreSignal: 2006024598e40c84666cc311a42c256bbf880db3ac99sewardj post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size ); 2007024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 2008024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 2009024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 2010024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2011024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2012024598e40c84666cc311a42c256bbf880db3ac99sewardj 2013c4431bfe04c7490ea2d74939d222d87f13f30960njnvoid h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset, 2014024598e40c84666cc311a42c256bbf880db3ac99sewardj SizeT size, Addr f ) 2015024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2016024598e40c84666cc311a42c256bbf880db3ac99sewardj UWord p; 2017024598e40c84666cc311a42c256bbf880db3ac99sewardj 2018024598e40c84666cc311a42c256bbf880db3ac99sewardj // Having to do this is a bit nasty... 2019024598e40c84666cc311a42c256bbf880db3ac99sewardj if (f == (Addr)h_replace_malloc 2020024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace___builtin_new 2021024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace___builtin_vec_new 2022024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace_calloc 2023024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace_memalign 2024024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace_realloc) 2025024598e40c84666cc311a42c256bbf880db3ac99sewardj { 2026024598e40c84666cc311a42c256bbf880db3ac99sewardj // We remembered the last added segment; make sure it's the right one. 2027024598e40c84666cc311a42c256bbf880db3ac99sewardj /* What's going on: at this point, the scheduler has just called 2028024598e40c84666cc311a42c256bbf880db3ac99sewardj 'f' -- one of our malloc replacement functions -- and it has 2029024598e40c84666cc311a42c256bbf880db3ac99sewardj returned. The return value has been written to the guest 2030024598e40c84666cc311a42c256bbf880db3ac99sewardj state of thread 'tid', offset 'guest_state_offset' length 2031024598e40c84666cc311a42c256bbf880db3ac99sewardj 'size'. We need to look at that return value and set the 2032024598e40c84666cc311a42c256bbf880db3ac99sewardj shadow return value accordingly. The shadow return value 2033024598e40c84666cc311a42c256bbf880db3ac99sewardj required is handed to us "under the counter" through the 2034024598e40c84666cc311a42c256bbf880db3ac99sewardj global variable 'last_seg_added'. This is all very ugly, not 2035024598e40c84666cc311a42c256bbf880db3ac99sewardj to mention, non-thread-safe should V ever become 2036024598e40c84666cc311a42c256bbf880db3ac99sewardj multithreaded. */ 2037024598e40c84666cc311a42c256bbf880db3ac99sewardj /* assert the place where the return value is is a legit int reg */ 2038024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(is_integer_guest_reg(guest_state_offset, size)); 2039024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Now we need to look at the returned value, to see whether the 2040024598e40c84666cc311a42c256bbf880db3ac99sewardj malloc succeeded or not. */ 2041024598e40c84666cc311a42c256bbf880db3ac99sewardj p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size); 2042024598e40c84666cc311a42c256bbf880db3ac99sewardj if ((UWord)NULL == p) { 2043024598e40c84666cc311a42c256bbf880db3ac99sewardj // if alloc failed, eg. realloc on bogus pointer 2044024598e40c84666cc311a42c256bbf880db3ac99sewardj put_guest_intreg(tid, 1/*first-shadow*/, 2045024598e40c84666cc311a42c256bbf880db3ac99sewardj guest_state_offset, size, (UWord)NONPTR ); 2046024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 2047024598e40c84666cc311a42c256bbf880db3ac99sewardj // alloc didn't fail. Check we have the correct segment. 2048024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(p == last_seg_added->addr); 2049024598e40c84666cc311a42c256bbf880db3ac99sewardj put_guest_intreg(tid, 1/*first-shadow*/, 2050024598e40c84666cc311a42c256bbf880db3ac99sewardj guest_state_offset, size, (UWord)last_seg_added ); 2051024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2052024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2053024598e40c84666cc311a42c256bbf880db3ac99sewardj else if (f == (Addr)h_replace_free 2054024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace___builtin_delete 2055024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)h_replace___builtin_vec_delete 2056024598e40c84666cc311a42c256bbf880db3ac99sewardj // || f == (Addr)VG_(cli_block_size) 2057024598e40c84666cc311a42c256bbf880db3ac99sewardj || f == (Addr)VG_(message)) 2058024598e40c84666cc311a42c256bbf880db3ac99sewardj { 2059024598e40c84666cc311a42c256bbf880db3ac99sewardj // Probably best to set the (non-existent!) return value to 2060024598e40c84666cc311a42c256bbf880db3ac99sewardj // non-pointer. 2061024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(is_integer_guest_reg(guest_state_offset, size)); 2062024598e40c84666cc311a42c256bbf880db3ac99sewardj put_guest_intreg(tid, 1/*first-shadow*/, 2063024598e40c84666cc311a42c256bbf880db3ac99sewardj guest_state_offset, size, (UWord)NONPTR ); 2064024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2065024598e40c84666cc311a42c256bbf880db3ac99sewardj else { 2066024598e40c84666cc311a42c256bbf880db3ac99sewardj // Anything else, probably best to set return value to non-pointer. 2067024598e40c84666cc311a42c256bbf880db3ac99sewardj //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN); 2068024598e40c84666cc311a42c256bbf880db3ac99sewardj Char fbuf[100]; 2069024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("f = %#lx\n", f); 2070024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(get_fnname)(f, fbuf, 100); 2071024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("name = %s\n", fbuf); 2072024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(tool_panic)("argh: clientcall"); 2073024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2074024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2075024598e40c84666cc311a42c256bbf880db3ac99sewardj 2076024598e40c84666cc311a42c256bbf880db3ac99sewardj 2077024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/ 2078024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--- Sanity checking ---*/ 2079024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /*--------------------------------------------------------------------*/ 2080024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 2081024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* Check that nobody has spuriously claimed that the first or last 16 2082024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz pages (64 KB) of address space have become accessible. Failure of 2083024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz the following do not per se indicate an internal consistency 2084024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz problem, but they are so likely to that we really want to know 2085024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz about it if so. */ 2086024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool pc_replace_cheap_sanity_check) ( void ) 2087024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 2088024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (IS_DISTINGUISHED_SM(primary_map[0]) 2089024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* kludge: kernel drops a page up at top of address range for 2090024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz magic "optimized syscalls", so we can no longer check the 2091024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz highest page */ 2092024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* && IS_DISTINGUISHED_SM(primary_map[65535]) */ 2093024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz ) 2094024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 2095024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz else 2096024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return False; 2097024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 2098024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 2099024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Bool SK_(expensive_sanity_check) ( void ) 2100024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 2101024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz Int i; 2102024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 2103024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* Make sure nobody changed the distinguished secondary. */ 2104024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz for (i = 0; i < SEC_MAP_WORDS; i++) 2105024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (distinguished_secondary_map.vseg[i] != UNKNOWN) 2106024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return False; 2107024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 2108024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 2109024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 2110024598e40c84666cc311a42c256bbf880db3ac99sewardj 2111024598e40c84666cc311a42c256bbf880db3ac99sewardj 2112024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 2113024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- System calls ---*/ 2114024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 2115024598e40c84666cc311a42c256bbf880db3ac99sewardj 21161c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjvoid h_pre_syscall ( ThreadId tid, UInt sysno, 21171c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord* args, UInt nArgs ) 2118024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2119024598e40c84666cc311a42c256bbf880db3ac99sewardj /* we don't do anything at the pre-syscall point */ 2120024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2121024598e40c84666cc311a42c256bbf880db3ac99sewardj 2122024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The post-syscall table is a table of pairs (number, flag). 2123024598e40c84666cc311a42c256bbf880db3ac99sewardj 2124024598e40c84666cc311a42c256bbf880db3ac99sewardj 'flag' is only ever zero or one. If it is zero, it indicates that 2125024598e40c84666cc311a42c256bbf880db3ac99sewardj default handling for that syscall is required -- namely that the 2126024598e40c84666cc311a42c256bbf880db3ac99sewardj syscall is deemed to return NONPTR. This is the case for the vast 2127024598e40c84666cc311a42c256bbf880db3ac99sewardj majority of syscalls. If it is one then some special 2128024598e40c84666cc311a42c256bbf880db3ac99sewardj syscall-specific handling is is required. No further details of it 2129024598e40c84666cc311a42c256bbf880db3ac99sewardj are stored in the table. 2130024598e40c84666cc311a42c256bbf880db3ac99sewardj 2131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn On Linux and Darwin, 'number' is a __NR_xxx constant. 2132024598e40c84666cc311a42c256bbf880db3ac99sewardj 2133024598e40c84666cc311a42c256bbf880db3ac99sewardj On AIX5, 'number' is an Int*, which points to the Int variable 2134024598e40c84666cc311a42c256bbf880db3ac99sewardj holding the currently assigned number for this syscall. 2135024598e40c84666cc311a42c256bbf880db3ac99sewardj 2136024598e40c84666cc311a42c256bbf880db3ac99sewardj When querying the table, we compare the supplied syscall number 2137f76d27a697a7b0bf3b84490baf60623fc96a23afnjn with the 'number' field (directly on Linux and Darwin, after 2138f76d27a697a7b0bf3b84490baf60623fc96a23afnjn dereferencing on AIX5), to find the relevant entry. This requires a 2139f76d27a697a7b0bf3b84490baf60623fc96a23afnjn linear search of the table. To stop the costs getting too high, the 2140f76d27a697a7b0bf3b84490baf60623fc96a23afnjn table is incrementally rearranged after each search, to move commonly 2141024598e40c84666cc311a42c256bbf880db3ac99sewardj requested items a bit closer to the front. 2142024598e40c84666cc311a42c256bbf880db3ac99sewardj 2143024598e40c84666cc311a42c256bbf880db3ac99sewardj The table is built once, the first time it is used. After that we 2144024598e40c84666cc311a42c256bbf880db3ac99sewardj merely query it (and reorder the entries as a result). */ 2145024598e40c84666cc311a42c256bbf880db3ac99sewardj 2146024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic XArray* /* of UWordPair */ post_syscall_table = NULL; 2147024598e40c84666cc311a42c256bbf880db3ac99sewardj 2148024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void setup_post_syscall_table ( void ) 2149024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2150024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(!post_syscall_table); 2151024598e40c84666cc311a42c256bbf880db3ac99sewardj post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1", 2152024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(free), sizeof(UWordPair) ); 2153024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(post_syscall_table); 2154024598e40c84666cc311a42c256bbf880db3ac99sewardj 2155024598e40c84666cc311a42c256bbf880db3ac99sewardj /* --------------- LINUX --------------- */ 2156024598e40c84666cc311a42c256bbf880db3ac99sewardj 2157024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(VGO_linux) 2158024598e40c84666cc311a42c256bbf880db3ac99sewardj 2159024598e40c84666cc311a42c256bbf880db3ac99sewardj# define ADD(_flag, _syscallname) \ 2160024598e40c84666cc311a42c256bbf880db3ac99sewardj do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \ 2161024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(addToXA)( post_syscall_table, &p ); \ 2162024598e40c84666cc311a42c256bbf880db3ac99sewardj } while (0) 2163024598e40c84666cc311a42c256bbf880db3ac99sewardj 2164024598e40c84666cc311a42c256bbf880db3ac99sewardj /* These ones definitely don't return pointers. They're not 2165024598e40c84666cc311a42c256bbf880db3ac99sewardj particularly grammatical, either. */ 2166024598e40c84666cc311a42c256bbf880db3ac99sewardj 2167024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR__llseek) 2168024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR__llseek); 2169024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2170024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR__sysctl); 2171024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR__newselect) 2172024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR__newselect); 2173024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2174024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_accept) 2175024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_accept); 2176024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2177024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_access); 2178332ffecd96becfaea1a67ddfab3e70372922393btom ADD(0, __NR_alarm); 2179024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_bind) 2180024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_bind); 2181024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2182024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_chdir) 2183024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_chdir); 2184024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2185024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_chmod); 2186024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_chown); 218741d5dea0b6d0672bd3986b5886e89b66941eef8asewardj# if defined(__NR_chown32) 218841d5dea0b6d0672bd3986b5886e89b66941eef8asewardj ADD(0, __NR_chown32); 218941d5dea0b6d0672bd3986b5886e89b66941eef8asewardj# endif 2190024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_clock_getres); 2191024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_clock_gettime); 2192024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_clone); 2193024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_close); 2194024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_connect) 2195024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_connect); 2196024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2197332ffecd96becfaea1a67ddfab3e70372922393btom ADD(0, __NR_creat); 2198024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_dup); 2199024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_dup2); 2200024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_execve); /* presumably we see this because the call failed? */ 2201024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_exit); /* hmm, why are we still alive? */ 2202024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_exit_group); 2203024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fadvise64); 22049f52ee49259e285335f2112e929b4183e354bc22sewardj ADD(0, __NR_fallocate); 2205024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fchmod); 2206024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fchown); 2207024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_fchown32) 2208024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fchown32); 2209024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2210024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fcntl); 2211024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_fcntl64) 2212024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fcntl64); 2213024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2214024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fdatasync); 221533c57f23131e434e28cd7993f17e5efbafff5db0sewardj ADD(0, __NR_flock); 2216024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fstat); 2217024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_fstat64) 2218024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fstat64); 2219024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2220024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fstatfs); 2221024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_fsync); 2222024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_ftruncate); 2223024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_ftruncate64) 2224024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_ftruncate64); 2225024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2226024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_futex); 2227024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getcwd); 2228024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getdents); // something to do with teeth 2229024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getdents64); 2230024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getegid); 2231024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_getegid32) 2232024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getegid32); 2233024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2234024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_geteuid); 2235024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_geteuid32) 2236024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_geteuid32); 2237024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2238024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getgid); 2239024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_getgid32) 2240024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getgid32); 2241024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2242ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj ADD(0, __NR_getgroups); 2243024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getitimer); 2244024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_getpeername) 2245024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getpeername); 2246024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2247024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getpid); 22487d7691194ba0f1011b341ccc517f8a474169f403sewardj ADD(0, __NR_getpgrp); 2249024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getppid); 2250024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getresgid); 2251024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getresuid); 22529f52ee49259e285335f2112e929b4183e354bc22sewardj# if defined(__NR_getresuid32) 22539f52ee49259e285335f2112e929b4183e354bc22sewardj ADD(0, __NR_getresuid32); 22549f52ee49259e285335f2112e929b4183e354bc22sewardj# endif 2255024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getrlimit); 2256332ffecd96becfaea1a67ddfab3e70372922393btom ADD(0, __NR_getrusage); 2257024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_getsockname) 2258024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getsockname); 2259024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2260024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_getsockopt) 2261024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getsockopt); 2262024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 226341d5dea0b6d0672bd3986b5886e89b66941eef8asewardj ADD(0, __NR_gettid); 2264024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_gettimeofday); 2265024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getuid); 2266024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_getuid32) 2267024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getuid32); 2268024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2269024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_getxattr); 2270738db7b86be4355d672d05bde9ad522d05fd2dfasewardj ADD(0, __NR_inotify_add_watch); 2271024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_inotify_init); 2272738db7b86be4355d672d05bde9ad522d05fd2dfasewardj ADD(0, __NR_inotify_rm_watch); 2273024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_ioctl); // ioctl -- assuming no pointers returned 227433c57f23131e434e28cd7993f17e5efbafff5db0sewardj ADD(0, __NR_ioprio_get); 2275024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_kill); 2276024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_link); 2277024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_listen) 2278024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_listen); 2279024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2280024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_lseek); 2281024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_lstat); 2282024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_lstat64) 2283024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_lstat64); 2284024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2285024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_madvise); 2286024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_mkdir); 228733c57f23131e434e28cd7993f17e5efbafff5db0sewardj ADD(0, __NR_mlock); 2288024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_mprotect); 2289024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_munmap); // die_mem_munmap already called, segment remove); 2290738db7b86be4355d672d05bde9ad522d05fd2dfasewardj ADD(0, __NR_nanosleep); 2291024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_open); 2292024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_pipe); 2293024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_poll); 2294024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_pread64); 2295024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_pwrite64); 2296024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_read); 2297024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_readlink); 2298024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_readv); 2299024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_recvfrom) 2300024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_recvfrom); 2301024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2302024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_recvmsg) 2303024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_recvmsg); 2304024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2305024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_rename); 2306024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_rmdir); 2307024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_rt_sigaction); 2308024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_rt_sigprocmask); 2309024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_rt_sigreturn); /* not sure if we should see this or not */ 2310024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sched_get_priority_max); 2311024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sched_get_priority_min); 2312738db7b86be4355d672d05bde9ad522d05fd2dfasewardj ADD(0, __NR_sched_getaffinity); 2313024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sched_getparam); 2314024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sched_getscheduler); 231541d5dea0b6d0672bd3986b5886e89b66941eef8asewardj ADD(0, __NR_sched_setaffinity); 2316024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sched_setscheduler); 2317024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sched_yield); 2318024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_select); 231933c57f23131e434e28cd7993f17e5efbafff5db0sewardj# if defined(__NR_semctl) 232033c57f23131e434e28cd7993f17e5efbafff5db0sewardj ADD(0, __NR_semctl); 232133c57f23131e434e28cd7993f17e5efbafff5db0sewardj# endif 232233c57f23131e434e28cd7993f17e5efbafff5db0sewardj# if defined(__NR_semget) 232333c57f23131e434e28cd7993f17e5efbafff5db0sewardj ADD(0, __NR_semget); 232433c57f23131e434e28cd7993f17e5efbafff5db0sewardj# endif 232533c57f23131e434e28cd7993f17e5efbafff5db0sewardj# if defined(__NR_semop) 232633c57f23131e434e28cd7993f17e5efbafff5db0sewardj ADD(0, __NR_semop); 232733c57f23131e434e28cd7993f17e5efbafff5db0sewardj# endif 2328024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_sendto) 2329024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sendto); 2330024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2331332ffecd96becfaea1a67ddfab3e70372922393btom# if defined(__NR_sendmsg) 2332332ffecd96becfaea1a67ddfab3e70372922393btom ADD(0, __NR_sendmsg); 2333332ffecd96becfaea1a67ddfab3e70372922393btom# endif 2334024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_set_robust_list); 2335024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_set_thread_area) 2336024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_set_thread_area); 2337024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2338024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_set_tid_address); 2339ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj ADD(0, __NR_setfsgid); 2340ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj ADD(0, __NR_setfsuid); 2341ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj ADD(0, __NR_setgid); 2342024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_setitimer); 23437d7691194ba0f1011b341ccc517f8a474169f403sewardj ADD(0, __NR_setpgid); 2344ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj ADD(0, __NR_setresgid); 2345024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_setrlimit); 2346024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_setsid); 2347024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_setsockopt) 2348024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_setsockopt); 2349024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2350ad039497dd0c569cf336c493aed1f9a341ee1c8csewardj ADD(0, __NR_setuid); 2351024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_shmctl) 2352024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_shmctl); 2353024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_shmdt); 2354024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2355024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_shutdown) 2356024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_shutdown); 2357024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 235841d5dea0b6d0672bd3986b5886e89b66941eef8asewardj ADD(0, __NR_sigaltstack); 2359024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_socket) 2360024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_socket); 2361024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2362024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_socketcall) 2363024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */ 2364024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 236523e8a29882812f4b1d33d6fb9719f779becfba6esewardj# if defined(__NR_socketpair) 236623e8a29882812f4b1d33d6fb9719f779becfba6esewardj ADD(0, __NR_socketpair); 236723e8a29882812f4b1d33d6fb9719f779becfba6esewardj# endif 2368024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_statfs64) 2369024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_statfs64); 2370024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2371024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_sigreturn) 2372024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sigreturn); /* not sure if we should see this or not */ 2373024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2374024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_stat64) 2375024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_stat64); 2376024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2377024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_stat); 2378024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_statfs); 2379024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_symlink); 2380024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_sysinfo); 2381024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_tgkill); 2382024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_time); 2383024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_times); 2384024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_truncate); 2385024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_truncate64) 2386024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_truncate64); 2387024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2388024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_ugetrlimit) 2389024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_ugetrlimit); 2390024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2391024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_umask); 2392024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_uname); 2393024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_unlink); 2394024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_utime); 2395024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_waitpid) 2396024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_waitpid); 2397024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2398024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_wait4); 2399024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_write); 2400024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_writev); 2401024598e40c84666cc311a42c256bbf880db3ac99sewardj 2402024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Whereas the following need special treatment */ 2403024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_arch_prctl) 2404024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_arch_prctl); 2405024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2406024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_brk); 2407024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_mmap); 2408024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_mmap2) 2409024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_mmap2); 2410024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2411024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_shmat) 2412024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_shmat); 2413024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2414024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_shmget) 2415024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_shmget); 2416024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 24171c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if defined(__NR_ipc) && defined(VKI_SHMAT) 24181c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj ADD(1, __NR_ipc); /* ppc{32,64}-linux horrors */ 24191c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 2420024598e40c84666cc311a42c256bbf880db3ac99sewardj 2421024598e40c84666cc311a42c256bbf880db3ac99sewardj /* --------------- AIX5 --------------- */ 2422024598e40c84666cc311a42c256bbf880db3ac99sewardj 2423024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGO_aix5) 2424024598e40c84666cc311a42c256bbf880db3ac99sewardj 2425024598e40c84666cc311a42c256bbf880db3ac99sewardj# define ADD(_flag, _syscallname) \ 2426024598e40c84666cc311a42c256bbf880db3ac99sewardj do { \ 2427024598e40c84666cc311a42c256bbf880db3ac99sewardj UWordPair p; \ 2428024598e40c84666cc311a42c256bbf880db3ac99sewardj if ((_syscallname) != __NR_AIX5_UNKNOWN) { \ 2429024598e40c84666cc311a42c256bbf880db3ac99sewardj p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \ 2430024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(addToXA)( post_syscall_table, &p ); \ 2431024598e40c84666cc311a42c256bbf880db3ac99sewardj } \ 2432024598e40c84666cc311a42c256bbf880db3ac99sewardj } while (0) 2433024598e40c84666cc311a42c256bbf880db3ac99sewardj 2434024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Just a minimal set of handlers, enough to make 2435024598e40c84666cc311a42c256bbf880db3ac99sewardj a 32- and 64-bit hello-world program run. */ 2436024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_AIX5___loadx); /* not sure what to do here */ 2437024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5__exit); 2438024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5_access); 2439024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5_getgidx); 2440024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5_getuidx); 2441024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5_kfcntl); 2442024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5_kioctl); 2443024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(1, __NR_AIX5_kload); /* not sure what to do here */ 2444024598e40c84666cc311a42c256bbf880db3ac99sewardj ADD(0, __NR_AIX5_kwrite); 2445024598e40c84666cc311a42c256bbf880db3ac99sewardj 2446f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* --------------- DARWIN ------------- */ 2447f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2448f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# elif defined(VGO_darwin) 2449f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2450f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# define ADD(_flag, _syscallname) \ 2451f76d27a697a7b0bf3b84490baf60623fc96a23afnjn do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \ 2452f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(addToXA)( post_syscall_table, &p ); \ 2453f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } while (0) 2454f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2455f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // DDD: a desultory attempt thus far... 2456f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2457f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Unix/BSD syscalls. 2458f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2459f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Mach traps. 2460f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ADD(0, __NR_host_self_trap); 2461f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ADD(0, __NR_mach_msg_trap); 2462f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ADD(0, __NR_mach_reply_port); 2463f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ADD(0, __NR_task_self_trap); 2464f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2465f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Machine-dependent syscalls. 24664e8808b021205659734885e2ca2665e225109b83njn ADD(0, __NR_thread_fast_set_cthread_self); 2467f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2468f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* ------------------------------------ */ 2469f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2470024598e40c84666cc311a42c256bbf880db3ac99sewardj# else 2471024598e40c84666cc311a42c256bbf880db3ac99sewardj# error "Unsupported OS" 2472024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2473024598e40c84666cc311a42c256bbf880db3ac99sewardj 2474024598e40c84666cc311a42c256bbf880db3ac99sewardj# undef ADD 2475024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2476024598e40c84666cc311a42c256bbf880db3ac99sewardj 2477024598e40c84666cc311a42c256bbf880db3ac99sewardj 24781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjvoid h_post_syscall ( ThreadId tid, UInt sysno, 24791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord* args, UInt nArgs, SysRes res ) 2480024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2481024598e40c84666cc311a42c256bbf880db3ac99sewardj Word i, n; 2482024598e40c84666cc311a42c256bbf880db3ac99sewardj UWordPair* pair; 2483024598e40c84666cc311a42c256bbf880db3ac99sewardj 2484024598e40c84666cc311a42c256bbf880db3ac99sewardj if (!post_syscall_table) 2485024598e40c84666cc311a42c256bbf880db3ac99sewardj setup_post_syscall_table(); 2486024598e40c84666cc311a42c256bbf880db3ac99sewardj 2487024598e40c84666cc311a42c256bbf880db3ac99sewardj /* search for 'sysno' in the post_syscall_table */ 2488024598e40c84666cc311a42c256bbf880db3ac99sewardj n = VG_(sizeXA)( post_syscall_table ); 2489024598e40c84666cc311a42c256bbf880db3ac99sewardj for (i = 0; i < n; i++) { 2490024598e40c84666cc311a42c256bbf880db3ac99sewardj pair = VG_(indexXA)( post_syscall_table, i ); 2491f76d27a697a7b0bf3b84490baf60623fc96a23afnjn# if defined(VGO_linux) || defined(VGO_darwin) 2492024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pair->uw1 == (UWord)sysno) 2493024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 2494024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGO_aix5) 2495024598e40c84666cc311a42c256bbf880db3ac99sewardj if (*(Int*)(pair->uw1) == (Int)sysno) 2496024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 2497024598e40c84666cc311a42c256bbf880db3ac99sewardj# else 2498024598e40c84666cc311a42c256bbf880db3ac99sewardj# error "Unsupported OS" 2499024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2500024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2501024598e40c84666cc311a42c256bbf880db3ac99sewardj 2502024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(i >= 0 && i <= n); 2503024598e40c84666cc311a42c256bbf880db3ac99sewardj 2504024598e40c84666cc311a42c256bbf880db3ac99sewardj if (i == n) { 25051a1e95c1f385a9b3b4f13f231eebaafff6e56450njn VG_(printf)("sysno == %s", VG_SYSNUM_STRING_EXTRA(sysno)); 2506024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(tool_panic)("unhandled syscall"); 2507024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2508024598e40c84666cc311a42c256bbf880db3ac99sewardj 2509024598e40c84666cc311a42c256bbf880db3ac99sewardj /* So we found the relevant entry. Move it one step 2510024598e40c84666cc311a42c256bbf880db3ac99sewardj forward so as to speed future accesses to it. */ 2511024598e40c84666cc311a42c256bbf880db3ac99sewardj if (i > 0) { 2512024598e40c84666cc311a42c256bbf880db3ac99sewardj UWordPair tmp, *p, *q; 2513024598e40c84666cc311a42c256bbf880db3ac99sewardj p = VG_(indexXA)( post_syscall_table, i-1 ); 2514024598e40c84666cc311a42c256bbf880db3ac99sewardj q = VG_(indexXA)( post_syscall_table, i-0 ); 2515024598e40c84666cc311a42c256bbf880db3ac99sewardj tmp = *p; 2516024598e40c84666cc311a42c256bbf880db3ac99sewardj *p = *q; 2517024598e40c84666cc311a42c256bbf880db3ac99sewardj *q = tmp; 2518024598e40c84666cc311a42c256bbf880db3ac99sewardj i--; 2519024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2520024598e40c84666cc311a42c256bbf880db3ac99sewardj 2521024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Deal with the common case */ 2522024598e40c84666cc311a42c256bbf880db3ac99sewardj pair = VG_(indexXA)( post_syscall_table, i ); 25231c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (pair->uw2 == 0) 25241c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* the common case */ 25251c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_NONPTR_err_NONPTR; 2526024598e40c84666cc311a42c256bbf880db3ac99sewardj 2527024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Special handling for all remaining cases */ 2528024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(pair->uw2 == 1); 2529024598e40c84666cc311a42c256bbf880db3ac99sewardj 2530024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_arch_prctl) 2531024598e40c84666cc311a42c256bbf880db3ac99sewardj if (sysno == __NR_arch_prctl) { 2532024598e40c84666cc311a42c256bbf880db3ac99sewardj /* This is nasty. On amd64-linux, arch_prctl may write a 2533024598e40c84666cc311a42c256bbf880db3ac99sewardj value to guest_FS_ZERO, and we need to shadow that value. 2534024598e40c84666cc311a42c256bbf880db3ac99sewardj Hence apply nonptr_or_unknown to it here, after the 2535024598e40c84666cc311a42c256bbf880db3ac99sewardj syscall completes. */ 2536024598e40c84666cc311a42c256bbf880db3ac99sewardj post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO, 2537024598e40c84666cc311a42c256bbf880db3ac99sewardj PC_SZB_FS_ZERO ); 25381c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_NONPTR_err_NONPTR; 2539024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2540024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2541024598e40c84666cc311a42c256bbf880db3ac99sewardj 2542024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_brk) 2543024598e40c84666cc311a42c256bbf880db3ac99sewardj // With brk(), result (of kernel syscall, not glibc wrapper) is a heap 2544024598e40c84666cc311a42c256bbf880db3ac99sewardj // pointer. Make the shadow UNKNOWN. 25451c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (sysno == __NR_brk) 25461c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_UNKNOWN_err_NONPTR; 2547024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2548024598e40c84666cc311a42c256bbf880db3ac99sewardj 2549024598e40c84666cc311a42c256bbf880db3ac99sewardj // With mmap, new_mem_mmap() has already been called and added the 2550024598e40c84666cc311a42c256bbf880db3ac99sewardj // segment (we did it there because we had the result address and size 2551024598e40c84666cc311a42c256bbf880db3ac99sewardj // handy). So just set the return value shadow. 2552024598e40c84666cc311a42c256bbf880db3ac99sewardj if (sysno == __NR_mmap 2553024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_mmap2) 2554024598e40c84666cc311a42c256bbf880db3ac99sewardj || sysno == __NR_mmap2 2555024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2556024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_AIX5___loadx) 2557024598e40c84666cc311a42c256bbf880db3ac99sewardj || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN) 2558024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2559024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_AIX5_kload) 2560024598e40c84666cc311a42c256bbf880db3ac99sewardj || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN) 2561024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2562024598e40c84666cc311a42c256bbf880db3ac99sewardj ) { 2563cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(res)) { 2564024598e40c84666cc311a42c256bbf880db3ac99sewardj // mmap() had an error, return value is a small negative integer 25651c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_NONPTR_err_NONPTR; 2566024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 25671c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_UNKNOWN_err_NONPTR; 2568024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2569024598e40c84666cc311a42c256bbf880db3ac99sewardj return; 2570024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2571024598e40c84666cc311a42c256bbf880db3ac99sewardj 2572024598e40c84666cc311a42c256bbf880db3ac99sewardj // shmat uses the same scheme. We will just have had a 2573024598e40c84666cc311a42c256bbf880db3ac99sewardj // notification via new_mem_mmap. Just set the return value shadow. 2574024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_shmat) 2575024598e40c84666cc311a42c256bbf880db3ac99sewardj if (sysno == __NR_shmat) { 2576cda2f0fbda4c4b2644babc830244be8aed95de1dnjn if (sr_isError(res)) { 25771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_NONPTR_err_NONPTR; 2578024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 25791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_UNKNOWN_err_NONPTR; 2580024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2581024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2582024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2583024598e40c84666cc311a42c256bbf880db3ac99sewardj 2584024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(__NR_shmget) 25851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (sysno == __NR_shmget) 2586024598e40c84666cc311a42c256bbf880db3ac99sewardj // FIXME: is this correct? 25871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_UNKNOWN_err_NONPTR; 25881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 25891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 25901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if defined(__NR_ipc) && defined(VKI_SHMAT) 25911c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* perhaps this should be further conditionalised with 25921c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj && (defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) 25931c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj Note, this just copies the behaviour of __NR_shmget above. 25941c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 25951c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj JRS 2009 June 02: it seems that the return value from 25961c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj sys_ipc(VKI_SHMAT, ...) doesn't have much relationship to the 25971c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj result returned by the originating user-level shmat call. It's 25981c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj different (and much lower) by a large but integral number of 25991c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj pages. I don't have time to chase this right now. Observed on 26001c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj ppc{32,64}-linux. Result appears to be false errors from apps 26011c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj using shmat. Confusion though -- shouldn't be related to the 26021c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj actual numeric values returned by the syscall, though, should 26031c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj it? Confused. Maybe some bad interaction with a 26041c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj nonpointer-or-unknown heuristic? */ 26051c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (sysno == __NR_ipc) { 26061c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (args[0] == VKI_SHMAT) { 26071c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_UNKNOWN_err_NONPTR; 26081c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } else { 26091c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto res_NONPTR_err_NONPTR; 26101c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 2611024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2612024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2613024598e40c84666cc311a42c256bbf880db3ac99sewardj 2614024598e40c84666cc311a42c256bbf880db3ac99sewardj /* If we get here, it implies the corresponding entry in 2615024598e40c84666cc311a42c256bbf880db3ac99sewardj post_syscall_table has .w2 == 1, which in turn implies there 2616024598e40c84666cc311a42c256bbf880db3ac99sewardj should be special-case code for it above. */ 2617024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 26181c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 26191c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj res_NONPTR_err_NONPTR: 26201c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj VG_(set_syscall_return_shadows)( tid, /* retval */ (UWord)NONPTR, 0, 26211c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* error */ (UWord)NONPTR, 0 ); 26221c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return; 26231c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 26241c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj res_UNKNOWN_err_NONPTR: 26251c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj VG_(set_syscall_return_shadows)( tid, /* retval */ (UWord)UNKNOWN, 0, 26261c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* error */ (UWord)NONPTR, 0 ); 26271c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return; 2628024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2629024598e40c84666cc311a42c256bbf880db3ac99sewardj 2630024598e40c84666cc311a42c256bbf880db3ac99sewardj 2631024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 2632024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Functions called from generated code ---*/ 2633024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 2634024598e40c84666cc311a42c256bbf880db3ac99sewardj 2635024598e40c84666cc311a42c256bbf880db3ac99sewardj#if SC_SEGS 2636024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void checkSeg ( Seg vseg ) { 2637024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM 2638024598e40c84666cc311a42c256bbf880db3ac99sewardj || Seg__plausible(vseg) ); 2639024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2640024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif 2641024598e40c84666cc311a42c256bbf880db3ac99sewardj 2642024598e40c84666cc311a42c256bbf880db3ac99sewardj// XXX: could be more sophisticated -- actually track the lowest/highest 2643024598e40c84666cc311a42c256bbf880db3ac99sewardj// valid address used by the program, and then return False for anything 2644024598e40c84666cc311a42c256bbf880db3ac99sewardj// below that (using a suitable safety margin). Also, nothing above 2645024598e40c84666cc311a42c256bbf880db3ac99sewardj// 0xc0000000 is valid [unless you've changed that in your kernel] 2646024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline Bool looks_like_a_pointer(Addr a) 2647024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2648024598e40c84666cc311a42c256bbf880db3ac99sewardj# if defined(VGA_x86) || defined(VGA_ppc32) 2649024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 4); 2650024598e40c84666cc311a42c256bbf880db3ac99sewardj return (a > 0x01000000UL && a < 0xFF000000UL); 2651024598e40c84666cc311a42c256bbf880db3ac99sewardj# elif defined(VGA_amd64) || defined(VGA_ppc64) 2652024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 8); 2653024598e40c84666cc311a42c256bbf880db3ac99sewardj return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL); 2654024598e40c84666cc311a42c256bbf880db3ac99sewardj# else 2655024598e40c84666cc311a42c256bbf880db3ac99sewardj# error "Unsupported architecture" 2656024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2657024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2658024598e40c84666cc311a42c256bbf880db3ac99sewardj 2659024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline VG_REGPARM(1) 2660024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* nonptr_or_unknown(UWord x) 2661024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2662024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR; 2663024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n", 2664024598e40c84666cc311a42c256bbf880db3ac99sewardj res==UNKNOWN ? "UUU" : "nnn", x); 2665024598e40c84666cc311a42c256bbf880db3ac99sewardj return res; 2666024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2667024598e40c84666cc311a42c256bbf880db3ac99sewardj 2668024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static __attribute__((regparm(1))) 2669024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz void print_BB_entry(UInt bb) 2670024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 2671024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz VG_(printf)("%u =\n", bb); 2672024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 2673024598e40c84666cc311a42c256bbf880db3ac99sewardj 267459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__tot_mem_refs = 0; 267559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__refs_in_a_seg = 0; 267659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static ULong stats__refs_lost_seg = 0; 2677024598e40c84666cc311a42c256bbf880db3ac99sewardj 2678024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef 2679024598e40c84666cc311a42c256bbf880db3ac99sewardj struct { ExeContext* ec; UWord count; } 2680024598e40c84666cc311a42c256bbf880db3ac99sewardj Lossage; 2681024598e40c84666cc311a42c256bbf880db3ac99sewardj 2682024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic OSet* lossage = NULL; 2683024598e40c84666cc311a42c256bbf880db3ac99sewardj 268459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static void inc_lossage ( ExeContext* ec ) 268559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//{ 268659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// Lossage key, *res, *nyu; 268759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// key.ec = ec; 268859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// key.count = 0; /* frivolous */ 268959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// res = VG_(OSetGen_Lookup)(lossage, &key); 269059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// if (res) { 269159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// tl_assert(res->ec == ec); 269259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// res->count++; 269359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// } else { 269459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage)); 269559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// tl_assert(nyu); 269659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// nyu->ec = ec; 269759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// nyu->count = 1; 269859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// VG_(OSetGen_Insert)( lossage, nyu ); 269959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// } 270059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//} 2701024598e40c84666cc311a42c256bbf880db3ac99sewardj 2702024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void init_lossage ( void ) 2703024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2704024598e40c84666cc311a42c256bbf880db3ac99sewardj lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec), 2705024598e40c84666cc311a42c256bbf880db3ac99sewardj /*fastCmp*/NULL, 2706024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(malloc), "pc.h_main.il.1", 2707024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(free) ); 2708024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(lossage); 2709024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2710024598e40c84666cc311a42c256bbf880db3ac99sewardj 271159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//static void show_lossage ( void ) 271259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//{ 271359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// Lossage* elem; 271459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// VG_(OSetGen_ResetIter)( lossage ); 271559347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// while ( (elem = VG_(OSetGen_Next)(lossage)) ) { 271659347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// if (elem->count < 10) continue; 271759347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// //Char buf[100]; 271859347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1); 271959347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// //buf[sizeof(buf)-1] = 0; 272059347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// //VG_(printf)(" %,8lu %s\n", elem->count, buf); 272159347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count); 272259347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// VG_(pp_ExeContext)(elem->ec); 272359347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj// } 272459347ff977da9dbee4a57b0cd5b0fc20f0d1e677sewardj//} 2725024598e40c84666cc311a42c256bbf880db3ac99sewardj 2726024598e40c84666cc311a42c256bbf880db3ac99sewardj// This function is called *a lot*; inlining it sped up Konqueror by 20%. 2727024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline 2728024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg) 2729024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2730024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0 27314815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj tl_assert(0); 27324815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj if (h_clo_lossage_check) { 2733024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* seg; 2734024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__tot_mem_refs++; 2735024598e40c84666cc311a42c256bbf880db3ac99sewardj if (ISList__findI0( seglist, (Addr)m, &seg )) { 2736024598e40c84666cc311a42c256bbf880db3ac99sewardj /* m falls inside 'seg' (that is, we are making a memory 2737024598e40c84666cc311a42c256bbf880db3ac99sewardj reference inside 'seg'). Now, really mptr_vseg should be 2738024598e40c84666cc311a42c256bbf880db3ac99sewardj a tracked segment of some description. Badness is when 2739024598e40c84666cc311a42c256bbf880db3ac99sewardj mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point, 2740024598e40c84666cc311a42c256bbf880db3ac99sewardj since that means we've lost the type of it somehow: it 2741024598e40c84666cc311a42c256bbf880db3ac99sewardj shoud say that m points into a real segment (preferable 2742024598e40c84666cc311a42c256bbf880db3ac99sewardj 'seg'), but it doesn't. */ 2743024598e40c84666cc311a42c256bbf880db3ac99sewardj if (Seg__status_is_SegHeap(seg)) { 2744024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__refs_in_a_seg++; 2745024598e40c84666cc311a42c256bbf880db3ac99sewardj if (UNKNOWN == mptr_vseg 2746024598e40c84666cc311a42c256bbf880db3ac99sewardj || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) { 2747024598e40c84666cc311a42c256bbf880db3ac99sewardj ExeContext* ec; 2748024598e40c84666cc311a42c256bbf880db3ac99sewardj Char buf[100]; 2749024598e40c84666cc311a42c256bbf880db3ac99sewardj static UWord xx = 0; 2750024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__refs_lost_seg++; 2751024598e40c84666cc311a42c256bbf880db3ac99sewardj ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 ); 2752024598e40c84666cc311a42c256bbf880db3ac99sewardj inc_lossage(ec); 2753024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0) { 2754024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_DebugMsg, ""); 2755024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_DebugMsg, 2756024598e40c84666cc311a42c256bbf880db3ac99sewardj "Lossage %s %#lx sz %lu inside block alloc'd", 2757024598e40c84666cc311a42c256bbf880db3ac99sewardj is_write ? "wr" : "rd", m, (UWord)sz); 2758024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(pp_ExeContext)(Seg__where(seg)); 2759024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2760024598e40c84666cc311a42c256bbf880db3ac99sewardj if (xx++ < 0) { 2761024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr ip = VG_(get_IP)( VG_(get_running_tid)() ); 2762024598e40c84666cc311a42c256bbf880db3ac99sewardj (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1); 2763024598e40c84666cc311a42c256bbf880db3ac99sewardj buf[sizeof(buf)-1] = 0; 2764024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("lossage at %p %s\n", ec, buf ); 2765024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2766024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2767024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2768024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2769024598e40c84666cc311a42c256bbf880db3ac99sewardj } /* clo_lossage_check */ 27704815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#endif 2771024598e40c84666cc311a42c256bbf880db3ac99sewardj 2772024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2773024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2774024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2775024598e40c84666cc311a42c256bbf880db3ac99sewardj 2776024598e40c84666cc311a42c256bbf880db3ac99sewardj if (UNKNOWN == mptr_vseg) { 2777024598e40c84666cc311a42c256bbf880db3ac99sewardj // do nothing 2778024598e40c84666cc311a42c256bbf880db3ac99sewardj 2779024598e40c84666cc311a42c256bbf880db3ac99sewardj } else if (BOTTOM == mptr_vseg) { 2780024598e40c84666cc311a42c256bbf880db3ac99sewardj // do nothing 2781024598e40c84666cc311a42c256bbf880db3ac99sewardj 2782024598e40c84666cc311a42c256bbf880db3ac99sewardj } else if (NONPTR == mptr_vseg) { 2783024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_heap_error( m, sz, mptr_vseg, is_write ); 2784024598e40c84666cc311a42c256bbf880db3ac99sewardj 2785024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 2786024598e40c84666cc311a42c256bbf880db3ac99sewardj // check all segment ranges in the circle 2787024598e40c84666cc311a42c256bbf880db3ac99sewardj // if none match, warn about 1st seg 2788024598e40c84666cc311a42c256bbf880db3ac99sewardj // else, check matching one isn't freed 2789024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool is_ok = False; 2790024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* curr = mptr_vseg; 2791024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr mhi; 2792024598e40c84666cc311a42c256bbf880db3ac99sewardj 2793024598e40c84666cc311a42c256bbf880db3ac99sewardj // Accesses partly outside range are an error, unless it's an aligned 2794024598e40c84666cc311a42c256bbf880db3ac99sewardj // word-sized read, and --partial-loads-ok=yes. This is to cope with 2795024598e40c84666cc311a42c256bbf880db3ac99sewardj // gcc's/glibc's habits of doing word-sized accesses that read past 2796024598e40c84666cc311a42c256bbf880db3ac99sewardj // the ends of arrays/strings. 2797024598e40c84666cc311a42c256bbf880db3ac99sewardj // JRS 2008-sept-11: couldn't this be moved off the critical path? 2798024598e40c84666cc311a42c256bbf880db3ac99sewardj if (!is_write && sz == sizeof(UWord) 2799024598e40c84666cc311a42c256bbf880db3ac99sewardj && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) { 2800024598e40c84666cc311a42c256bbf880db3ac99sewardj mhi = m; 2801024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 2802024598e40c84666cc311a42c256bbf880db3ac99sewardj mhi = m+sz-1; 2803024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2804024598e40c84666cc311a42c256bbf880db3ac99sewardj 2805024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi); 2806024598e40c84666cc311a42c256bbf880db3ac99sewardj is_ok = curr->addr <= m && mhi < curr->addr + curr->szB; 2807024598e40c84666cc311a42c256bbf880db3ac99sewardj 2808024598e40c84666cc311a42c256bbf880db3ac99sewardj // If it's an overrun/underrun of a freed block, don't give both 2809024598e40c84666cc311a42c256bbf880db3ac99sewardj // warnings, since the first one mentions that the block has been 2810024598e40c84666cc311a42c256bbf880db3ac99sewardj // freed. 2811024598e40c84666cc311a42c256bbf880db3ac99sewardj if ( ! is_ok || Seg__is_freed(curr) ) 2812024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_heap_error( m, sz, mptr_vseg, is_write ); 2813024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2814024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2815024598e40c84666cc311a42c256bbf880db3ac99sewardj 2816024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Load handlers ------------------ // 2817024598e40c84666cc311a42c256bbf880db3ac99sewardj 2818024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use: 2819024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load1 check_load2 check_load4_P 2820024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load4 (for 32-bit FP reads) 2821024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load8 (for 64-bit FP reads) 2822024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load16 (for xmm/altivec reads) 2823024598e40c84666cc311a42c256bbf880db3ac99sewardj On 64 bit targets, we will use: 2824024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load1 check_load2 check_load4 check_load8_P 2825024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load8 (for 64-bit FP reads) 2826024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load16 (for xmm/altivec reads) 2827024598e40c84666cc311a42c256bbf880db3ac99sewardj 2828024598e40c84666cc311a42c256bbf880db3ac99sewardj A "_P" handler reads a pointer from memory, and so returns a value 2829024598e40c84666cc311a42c256bbf880db3ac99sewardj to the generated code -- the pointer's shadow value. That implies 2830024598e40c84666cc311a42c256bbf880db3ac99sewardj that check_load4_P is only to be called on a 32 bit host and 2831024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load8_P is only to be called on a 64 bit host. For all other 2832024598e40c84666cc311a42c256bbf880db3ac99sewardj cases no shadow value is returned; we merely check that the pointer 2833024598e40c84666cc311a42c256bbf880db3ac99sewardj (m) matches the block described by its shadow value (mptr_vseg). 2834024598e40c84666cc311a42c256bbf880db3ac99sewardj*/ 2835024598e40c84666cc311a42c256bbf880db3ac99sewardj 2836024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit loads on both 32 bit and 64 bit targets. 2837024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2838024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load16(Addr m, Seg* mptr_vseg) 2839024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2840024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2841024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2842024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2843024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 16, mptr_vseg); 2844024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2845024598e40c84666cc311a42c256bbf880db3ac99sewardj 2846024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit FP-or-otherwise-nonpointer loads on both 2847024598e40c84666cc311a42c256bbf880db3ac99sewardj// 32 bit and 64 bit targets. 2848024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2849024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load8(Addr m, Seg* mptr_vseg) 2850024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2851024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2852024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2853024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2854024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 8, mptr_vseg); 2855024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2856024598e40c84666cc311a42c256bbf880db3ac99sewardj 2857024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit loads on 64 bit targets. It must 2858024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets. 2859024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg 2860024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2861024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load8_P(Addr m, Seg* mptr_vseg) 2862024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2863024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* vseg; 2864024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */ 2865024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2866024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2867024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2868024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 8, mptr_vseg); 2869024598e40c84666cc311a42c256bbf880db3ac99sewardj if (VG_IS_8_ALIGNED(m)) { 2870024598e40c84666cc311a42c256bbf880db3ac99sewardj vseg = get_mem_vseg(m); 2871024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 2872024598e40c84666cc311a42c256bbf880db3ac99sewardj vseg = nonptr_or_unknown( *(ULong*)m ); 2873024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2874024598e40c84666cc311a42c256bbf880db3ac99sewardj return vseg; 2875024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2876024598e40c84666cc311a42c256bbf880db3ac99sewardj 2877024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit loads on 32 bit targets. It must 2878024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets. 2879024598e40c84666cc311a42c256bbf880db3ac99sewardj// return m.vseg 2880024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2881024598e40c84666cc311a42c256bbf880db3ac99sewardjSeg* check_load4_P(Addr m, Seg* mptr_vseg) 2882024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2883024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* vseg; 2884024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */ 2885024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2886024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2887024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2888024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 4, mptr_vseg); 2889024598e40c84666cc311a42c256bbf880db3ac99sewardj if (VG_IS_4_ALIGNED(m)) { 2890024598e40c84666cc311a42c256bbf880db3ac99sewardj vseg = get_mem_vseg(m); 2891024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 2892024598e40c84666cc311a42c256bbf880db3ac99sewardj vseg = nonptr_or_unknown( *(UInt*)m ); 2893024598e40c84666cc311a42c256bbf880db3ac99sewardj } 2894024598e40c84666cc311a42c256bbf880db3ac99sewardj return vseg; 2895024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2896024598e40c84666cc311a42c256bbf880db3ac99sewardj 2897024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets. 2898024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2899024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load4(Addr m, Seg* mptr_vseg) 2900024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2901024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2902024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2903024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2904024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 4, mptr_vseg); 2905024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2906024598e40c84666cc311a42c256bbf880db3ac99sewardj 2907024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets. 2908024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2909024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load2(Addr m, Seg* mptr_vseg) 2910024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2911024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2912024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2913024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2914024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 2, mptr_vseg); 2915024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2916024598e40c84666cc311a42c256bbf880db3ac99sewardj 2917024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets. 2918024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 2919024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_load1(Addr m, Seg* mptr_vseg) 2920024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 2921024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 2922024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 2923024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 2924024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/False, m, 1, mptr_vseg); 2925024598e40c84666cc311a42c256bbf880db3ac99sewardj} 2926024598e40c84666cc311a42c256bbf880db3ac99sewardj 2927024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------------ Store handlers ------------------ // 2928024598e40c84666cc311a42c256bbf880db3ac99sewardj 2929024598e40c84666cc311a42c256bbf880db3ac99sewardj/* On 32 bit targets, we will use: 29301c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_store1 check_store2 check_store4_P check_store4C_P 2931024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store4 (for 32-bit nonpointer stores) 2932024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store8_ms4B_ls4B (for 64-bit stores) 2933024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores) 2934024598e40c84666cc311a42c256bbf880db3ac99sewardj 2935024598e40c84666cc311a42c256bbf880db3ac99sewardj On 64 bit targets, we will use: 29361c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_store1 check_store2 check_store4 check_store4C 29371c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_store8_P check_store_8C_P 2938024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store8_all8B (for 64-bit nonpointer stores) 2939024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store16_ms8B_ls8B (for xmm/altivec stores) 2940024598e40c84666cc311a42c256bbf880db3ac99sewardj 2941024598e40c84666cc311a42c256bbf880db3ac99sewardj A "_P" handler writes a pointer to memory, and so has an extra 2942024598e40c84666cc311a42c256bbf880db3ac99sewardj argument -- the pointer's shadow value. That implies that 29431c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_store4{,C}_P is only to be called on a 32 bit host and 29441c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_store8{,C}_P is only to be called on a 64 bit host. For all 2945024598e40c84666cc311a42c256bbf880db3ac99sewardj other cases, and for the misaligned _P cases, the strategy is to 2946024598e40c84666cc311a42c256bbf880db3ac99sewardj let the store go through, and then snoop around with 2947024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown to fix up the shadow values of any affected 2948024598e40c84666cc311a42c256bbf880db3ac99sewardj words. */ 2949024598e40c84666cc311a42c256bbf880db3ac99sewardj 29501c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj/* Helpers for store-conditionals. Ugly kludge :-( 29511c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj They all return 1 if the SC was successful and 0 if it failed. */ 29521c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic inline UWord do_store_conditional_32( Addr m/*dst*/, UInt t/*val*/ ) 29531c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{ 29541c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if defined(VGA_ppc32) || defined(VGA_ppc64) 29551c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord success; 29561c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* If this assertion fails, the underlying IR is (semantically) ill-formed 29571c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj as per the IR spec for IRStmt_Store. */ 29581c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(VG_IS_4_ALIGNED(m)); 29591c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj __asm__ __volatile__( 29601c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "stwcx. %2,0,%1" "\n\t" /* data,0,addr */ 29611c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "mfcr %0" "\n\t" 29621c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "srwi %0,%0,29" "\n\t" /* move relevant CR bit to LSB */ 29631c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj : /*out*/"=b"(success) 29641c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj : /*in*/ "b"(m), "b"( (UWord)t ) 29651c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj : /*trash*/ "memory", "cc" 29661c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* Note: srwi is OK even on 64-bit host because the we're 29671c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj after bit 29 (normal numbering) and we mask off all the 29681c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj other junk just below. */ 29691c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj ); 29701c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return success & (UWord)1; 29711c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# else 29721c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(0); /* not implemented on other platforms */ 29731c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 29741c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj} 29751c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 29761c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic inline UWord do_store_conditional_64( Addr m/*dst*/, ULong t/*val*/ ) 29771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{ 29781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if defined(VGA_ppc64) 29791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord success; 29801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* If this assertion fails, the underlying IR is (semantically) ill-formed 29811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj as per the IR spec for IRStmt_Store. */ 29821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(VG_IS_8_ALIGNED(m)); 29831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj __asm__ __volatile__( 29841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "stdcx. %2,0,%1" "\n\t" /* data,0,addr */ 29851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "mfcr %0" "\n\t" 29861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "srdi %0,%0,29" "\n\t" /* move relevant CR bit to LSB */ 29871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj : /*out*/"=b"(success) 29881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj : /*in*/ "b"(m), "b"( (UWord)t ) 29891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj : /*trash*/ "memory", "cc" 29901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj ); 29911c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return success & (UWord)1; 29921c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# else 29931c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(0); /* not implemented on other platforms */ 29941c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 29951c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj} 29961c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 2997024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Apply nonptr_or_unknown to all the words intersecting 2998024598e40c84666cc311a42c256bbf880db3ac99sewardj [a, a+len). */ 2999024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) 3000024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid nonptr_or_unknown_range ( Addr a, SizeT len ) 3001024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3002024598e40c84666cc311a42c256bbf880db3ac99sewardj const SizeT wszB = sizeof(UWord); 3003024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr wfirst = VG_ROUNDDN(a, wszB); 3004024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr wlast = VG_ROUNDDN(a+len-1, wszB); 3005024598e40c84666cc311a42c256bbf880db3ac99sewardj Addr a2; 3006024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(wfirst <= wlast); 3007024598e40c84666cc311a42c256bbf880db3ac99sewardj for (a2 = wfirst ; a2 <= wlast; a2 += wszB) { 3008024598e40c84666cc311a42c256bbf880db3ac99sewardj set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 )); 3009024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3010024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3011024598e40c84666cc311a42c256bbf880db3ac99sewardj 3012024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets. The 3013024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant 3014024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first. 3015024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3016024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg, 3017024598e40c84666cc311a42c256bbf880db3ac99sewardj UWord ms8B, UWord ls8B) 3018024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3019024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */ 3020024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3021024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3022024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3023024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 16, mptr_vseg); 3024024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here 3025024598e40c84666cc311a42c256bbf880db3ac99sewardj if (host_is_little_endian()) { 3026024598e40c84666cc311a42c256bbf880db3ac99sewardj // FIXME: aren't we really concerned whether the guest 3027024598e40c84666cc311a42c256bbf880db3ac99sewardj // is little endian, not whether the host is? 3028024598e40c84666cc311a42c256bbf880db3ac99sewardj *(ULong*)(m + 0) = ls8B; 3029024598e40c84666cc311a42c256bbf880db3ac99sewardj *(ULong*)(m + 8) = ms8B; 3030024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3031024598e40c84666cc311a42c256bbf880db3ac99sewardj *(ULong*)(m + 0) = ms8B; 3032024598e40c84666cc311a42c256bbf880db3ac99sewardj *(ULong*)(m + 8) = ls8B; 3033024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3034024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 16); 3035024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3036024598e40c84666cc311a42c256bbf880db3ac99sewardj 3037024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 128 bit stores on 64 bit targets. The 3038024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant 3039024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first. 3040024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3041024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg, 3042024598e40c84666cc311a42c256bbf880db3ac99sewardj UWord ms4B, UWord w2, 3043024598e40c84666cc311a42c256bbf880db3ac99sewardj UWord w1, UWord ls4B) 3044024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3045024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */ 3046024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3047024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3048024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3049024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 16, mptr_vseg); 3050024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here 3051024598e40c84666cc311a42c256bbf880db3ac99sewardj if (host_is_little_endian()) { 3052024598e40c84666cc311a42c256bbf880db3ac99sewardj // FIXME: aren't we really concerned whether the guest 3053024598e40c84666cc311a42c256bbf880db3ac99sewardj // is little endian, not whether the host is? 3054024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 0) = ls4B; 3055024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 4) = w1; 3056024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 8) = w2; 3057024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 12) = ms4B; 3058024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3059024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 0) = ms4B; 3060024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 4) = w2; 3061024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 8) = w1; 3062024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 12) = ls4B; 3063024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3064024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 16); 3065024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3066024598e40c84666cc311a42c256bbf880db3ac99sewardj 3067024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 32 bit targets. The 3068024598e40c84666cc311a42c256bbf880db3ac99sewardj// store data is passed in 2 pieces, the most significant 3069024598e40c84666cc311a42c256bbf880db3ac99sewardj// bits first. 3070024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3071024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg, 3072024598e40c84666cc311a42c256bbf880db3ac99sewardj UWord ms4B, UWord ls4B) 3073024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3074024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */ 3075024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3076024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3077024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3078024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 8, mptr_vseg); 3079024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here 3080024598e40c84666cc311a42c256bbf880db3ac99sewardj if (host_is_little_endian()) { 3081024598e40c84666cc311a42c256bbf880db3ac99sewardj // FIXME: aren't we really concerned whether the guest 3082024598e40c84666cc311a42c256bbf880db3ac99sewardj // is little endian, not whether the host is? 3083024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 0) = ls4B; 3084024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 4) = ms4B; 3085024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3086024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 0) = ms4B; 3087024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)(m + 4) = ls4B; 3088024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3089024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 8); 3090024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3091024598e40c84666cc311a42c256bbf880db3ac99sewardj 3092024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit non pointer stores on 64 bit targets. 3093024598e40c84666cc311a42c256bbf880db3ac99sewardj// It must not be called on 32 bit targets. 3094024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3095024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B) 3096024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3097024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */ 3098024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3099024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3100024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3101024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 8, mptr_vseg); 3102024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here 3103024598e40c84666cc311a42c256bbf880db3ac99sewardj *(ULong*)m = all8B; 3104024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 8); 3105024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3106024598e40c84666cc311a42c256bbf880db3ac99sewardj 3107024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 64 bit stores on 64 bit targets. It must 3108024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 32 bit targets. 3109024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3110024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg) 3111024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3112024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */ 3113024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3114024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(t_vseg); 3115024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3116024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3117024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 8, mptr_vseg); 3118024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here 3119024598e40c84666cc311a42c256bbf880db3ac99sewardj *(ULong*)m = t; 3120024598e40c84666cc311a42c256bbf880db3ac99sewardj if (VG_IS_8_ALIGNED(m)) { 3121024598e40c84666cc311a42c256bbf880db3ac99sewardj set_mem_vseg( m, t_vseg ); 3122024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3123024598e40c84666cc311a42c256bbf880db3ac99sewardj // straddling two words 3124024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 8); 3125024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3126024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3127024598e40c84666cc311a42c256bbf880db3ac99sewardj 31281c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// This handles 64 bit store-conditionals on 64 bit targets. It must 31291c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// not be called on 32 bit targets. 31301c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic VG_REGPARM(3) 31311c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjUWord check_store8C_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg) 31321c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{ 31331c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord success; 31341c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */ 31351c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if SC_SEGS 31361c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj checkSeg(t_vseg); 31371c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj checkSeg(mptr_vseg); 31381c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 31391c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_load_or_store(/*is_write*/True, m, 8, mptr_vseg); 31401c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj // Actually *do* the STORE here 31411c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj success = do_store_conditional_64( m, t ); 31421c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (VG_IS_8_ALIGNED(m)) { 31431c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj set_mem_vseg( m, t_vseg ); 31441c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } else { 31451c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj // straddling two words 31461c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj nonptr_or_unknown_range(m, 8); 31471c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 31481c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return success; 31491c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj} 31501c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 3151024598e40c84666cc311a42c256bbf880db3ac99sewardj// This handles 32 bit stores on 32 bit targets. It must 3152024598e40c84666cc311a42c256bbf880db3ac99sewardj// not be called on 64 bit targets. 3153024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3154024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg) 3155024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3156024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */ 3157024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3158024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(t_vseg); 3159024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3160024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3161024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 4, mptr_vseg); 3162024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here 3163024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)m = t; 3164024598e40c84666cc311a42c256bbf880db3ac99sewardj if (VG_IS_4_ALIGNED(m)) { 3165024598e40c84666cc311a42c256bbf880db3ac99sewardj set_mem_vseg( m, t_vseg ); 3166024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3167024598e40c84666cc311a42c256bbf880db3ac99sewardj // straddling two words 3168024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 4); 3169024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3170024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3171024598e40c84666cc311a42c256bbf880db3ac99sewardj 31721c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// This handles 32 bit store-conditionals on 32 bit targets. It must 31731c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// not be called on 64 bit targets. 31741c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic VG_REGPARM(3) 31751c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjUWord check_store4C_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg) 31761c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{ 31771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord success; 31781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */ 31791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if SC_SEGS 31801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj checkSeg(t_vseg); 31811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj checkSeg(mptr_vseg); 31821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 31831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_load_or_store(/*is_write*/True, m, 4, mptr_vseg); 31841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj // Actually *do* the STORE here 31851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj success = do_store_conditional_32( m, t ); 31861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (VG_IS_4_ALIGNED(m)) { 31871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj set_mem_vseg( m, t_vseg ); 31881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } else { 31891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj // straddling two words 31901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj nonptr_or_unknown_range(m, 4); 31911c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 31921c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return success; 31931c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj} 31941c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 3195024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets. 3196024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3197024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store4(Addr m, Seg* mptr_vseg, UWord t) 3198024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3199024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3200024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3201024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3202024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 4, mptr_vseg); 3203024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here (Nb: cast must be to 4-byte type!) 3204024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UInt*)m = t; 3205024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 4); 3206024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3207024598e40c84666cc311a42c256bbf880db3ac99sewardj 32081c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// Used for 32-bit store-conditionals on 64 bit targets only. It must 32091c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj// not be called on 32 bit targets. 32101c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjstatic VG_REGPARM(3) 32111c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardjUWord check_store4C(Addr m, Seg* mptr_vseg, UWord t) 32121c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj{ 32131c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj UWord success; 32141c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */ 32151c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# if SC_SEGS 32161c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj checkSeg(mptr_vseg); 32171c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj# endif 32181c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj check_load_or_store(/*is_write*/True, m, 4, mptr_vseg); 32191c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj // Actually *do* the STORE here 32201c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj success = do_store_conditional_32( m, t ); 32211c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj nonptr_or_unknown_range(m, 4); 32221c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj return success; 32231c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj} 32241c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 3225024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets. 3226024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3227024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store2(Addr m, Seg* mptr_vseg, UWord t) 3228024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3229024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3230024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3231024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3232024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 2, mptr_vseg); 3233024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here (Nb: cast must be to 2-byte type!) 3234024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UShort*)m = t; 3235024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 2); 3236024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3237024598e40c84666cc311a42c256bbf880db3ac99sewardj 3238024598e40c84666cc311a42c256bbf880db3ac99sewardj// Used for both 32 bit and 64 bit targets. 3239024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) 3240024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid check_store1(Addr m, Seg* mptr_vseg, UWord t) 3241024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3242024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3243024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(mptr_vseg); 3244024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3245024598e40c84666cc311a42c256bbf880db3ac99sewardj check_load_or_store(/*is_write*/True, m, 1, mptr_vseg); 3246024598e40c84666cc311a42c256bbf880db3ac99sewardj // Actually *do* the STORE here (Nb: cast must be to 1-byte type!) 3247024598e40c84666cc311a42c256bbf880db3ac99sewardj *(UChar*)m = t; 3248024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown_range(m, 1); 3249024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3250024598e40c84666cc311a42c256bbf880db3ac99sewardj 3251024598e40c84666cc311a42c256bbf880db3ac99sewardj 3252024598e40c84666cc311a42c256bbf880db3ac99sewardj// Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM 3253024598e40c84666cc311a42c256bbf880db3ac99sewardj// be changed to NONPTR by a range check on the result. 3254024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \ 3255024598e40c84666cc311a42c256bbf880db3ac99sewardj if (BOTTOM == seg1 || BOTTOM == seg2) { bt; \ 3256024598e40c84666cc311a42c256bbf880db3ac99sewardj } else if (NONPTR == seg1) { if (NONPTR == seg2) { nn; } \ 3257024598e40c84666cc311a42c256bbf880db3ac99sewardj else if (UNKNOWN == seg2) { nu; } \ 3258024598e40c84666cc311a42c256bbf880db3ac99sewardj else { np; } \ 3259024598e40c84666cc311a42c256bbf880db3ac99sewardj } else if (UNKNOWN == seg1) { if (NONPTR == seg2) { un; } \ 3260024598e40c84666cc311a42c256bbf880db3ac99sewardj else if (UNKNOWN == seg2) { uu; } \ 3261024598e40c84666cc311a42c256bbf880db3ac99sewardj else { up; } \ 3262024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { if (NONPTR == seg2) { pn; } \ 3263024598e40c84666cc311a42c256bbf880db3ac99sewardj else if (UNKNOWN == seg2) { pu; } \ 3264024598e40c84666cc311a42c256bbf880db3ac99sewardj else { pp; } \ 3265024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3266024598e40c84666cc311a42c256bbf880db3ac99sewardj 3267024598e40c84666cc311a42c256bbf880db3ac99sewardj#define BINERROR(opname) \ 3268024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_arith_error(seg1, seg2, opname); \ 3269024598e40c84666cc311a42c256bbf880db3ac99sewardj out = NONPTR 3270024598e40c84666cc311a42c256bbf880db3ac99sewardj 3271024598e40c84666cc311a42c256bbf880db3ac99sewardj 3272024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3273024598e40c84666cc311a42c256bbf880db3ac99sewardj// + | n ? p 3274024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3275024598e40c84666cc311a42c256bbf880db3ac99sewardj// n | n ? p 3276024598e40c84666cc311a42c256bbf880db3ac99sewardj// ? | ? ? ? 3277024598e40c84666cc311a42c256bbf880db3ac99sewardj// p | p ? e (all results become n if they look like a non-pointer) 3278024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3279024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname) 3280024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3281024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* out; 3282024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3283024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg1); 3284024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg2); 3285024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3286024598e40c84666cc311a42c256bbf880db3ac99sewardj BINOP( 3287024598e40c84666cc311a42c256bbf880db3ac99sewardj return BOTTOM, 3288024598e40c84666cc311a42c256bbf880db3ac99sewardj out = NONPTR, out = UNKNOWN, out = seg2, 3289024598e40c84666cc311a42c256bbf880db3ac99sewardj out = UNKNOWN, out = UNKNOWN, out = UNKNOWN, 3290024598e40c84666cc311a42c256bbf880db3ac99sewardj out = seg1, out = UNKNOWN, BINERROR(opname) 3291024598e40c84666cc311a42c256bbf880db3ac99sewardj ); 3292024598e40c84666cc311a42c256bbf880db3ac99sewardj return ( looks_like_a_pointer(result) ? out : NONPTR ); 3293024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3294024598e40c84666cc311a42c256bbf880db3ac99sewardj 3295024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result) 3296024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3297024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* out; 3298024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3299024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg1); 3300024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg2); 3301024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3302024598e40c84666cc311a42c256bbf880db3ac99sewardj out = do_addW_result(seg1, seg2, result, "Add32/Add64"); 3303024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3304024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(out); 3305024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3306024598e40c84666cc311a42c256bbf880db3ac99sewardj return out; 3307024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3308024598e40c84666cc311a42c256bbf880db3ac99sewardj 3309024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3310024598e40c84666cc311a42c256bbf880db3ac99sewardj// - | n ? p (Nb: operation is seg1 - seg2) 3311024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3312024598e40c84666cc311a42c256bbf880db3ac99sewardj// n | n ? n+ (+) happens a lot due to "cmp", but result should never 3313024598e40c84666cc311a42c256bbf880db3ac99sewardj// ? | ? ? n/B be used, so give 'n' 3314024598e40c84666cc311a42c256bbf880db3ac99sewardj// p | p p? n*/B (*) and possibly link the segments 3315024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3316024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result) 3317024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3318024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* out; 3319024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3320024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg1); 3321024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg2); 3322024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3323024598e40c84666cc311a42c256bbf880db3ac99sewardj // Nb: when returning BOTTOM, don't let it go through the range-check; 3324024598e40c84666cc311a42c256bbf880db3ac99sewardj // a segment linking offset can easily look like a nonptr. 3325024598e40c84666cc311a42c256bbf880db3ac99sewardj BINOP( 3326024598e40c84666cc311a42c256bbf880db3ac99sewardj return BOTTOM, 3327024598e40c84666cc311a42c256bbf880db3ac99sewardj out = NONPTR, out = UNKNOWN, out = NONPTR, 3328024598e40c84666cc311a42c256bbf880db3ac99sewardj out = UNKNOWN, out = UNKNOWN, return BOTTOM, 3329024598e40c84666cc311a42c256bbf880db3ac99sewardj out = seg1, out = seg1/*??*/, return BOTTOM 3330024598e40c84666cc311a42c256bbf880db3ac99sewardj ); 3331024598e40c84666cc311a42c256bbf880db3ac99sewardj #if 0 3332024598e40c84666cc311a42c256bbf880db3ac99sewardj // This is for the p-p segment-linking case 3333024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg end2 = seg2; 3334024598e40c84666cc311a42c256bbf880db3ac99sewardj while (end2->links != seg2) end2 = end2->links; 3335024598e40c84666cc311a42c256bbf880db3ac99sewardj end2->links = seg1->links; 3336024598e40c84666cc311a42c256bbf880db3ac99sewardj seg1->links = seg2; 3337024598e40c84666cc311a42c256bbf880db3ac99sewardj return NONPTR; 3338024598e40c84666cc311a42c256bbf880db3ac99sewardj #endif 3339024598e40c84666cc311a42c256bbf880db3ac99sewardj return ( looks_like_a_pointer(result) ? out : NONPTR ); 3340024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3341024598e40c84666cc311a42c256bbf880db3ac99sewardj 3342024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3343024598e40c84666cc311a42c256bbf880db3ac99sewardj// & | n ? p 3344024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3345024598e40c84666cc311a42c256bbf880db3ac99sewardj// n | n ? p 3346024598e40c84666cc311a42c256bbf880db3ac99sewardj// ? | ? ? ? 3347024598e40c84666cc311a42c256bbf880db3ac99sewardj// p | p ? * (*) if p1==p2 then p else e (see comment) 3348024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3349024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Seems to be OK to And two pointers: 3350024598e40c84666cc311a42c256bbf880db3ac99sewardj testq %ptr1,%ptr2 3351024598e40c84666cc311a42c256bbf880db3ac99sewardj jnz .. 3352024598e40c84666cc311a42c256bbf880db3ac99sewardj which possibly derives from 3353024598e40c84666cc311a42c256bbf880db3ac99sewardj if (ptr1 & ptr2) { A } else { B } 3354024598e40c84666cc311a42c256bbf880db3ac99sewardj not sure what that means 3355024598e40c84666cc311a42c256bbf880db3ac99sewardj*/ 3356024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2, 3357024598e40c84666cc311a42c256bbf880db3ac99sewardj UWord result, UWord args_diff) 3358024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3359024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* out; 3360024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0 == args_diff) { 3361024598e40c84666cc311a42c256bbf880db3ac99sewardj // p1==p2 3362024598e40c84666cc311a42c256bbf880db3ac99sewardj out = seg1; 3363024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3364024598e40c84666cc311a42c256bbf880db3ac99sewardj BINOP( 3365024598e40c84666cc311a42c256bbf880db3ac99sewardj return BOTTOM, 3366024598e40c84666cc311a42c256bbf880db3ac99sewardj out = NONPTR, out = UNKNOWN, out = seg2, 3367024598e40c84666cc311a42c256bbf880db3ac99sewardj out = UNKNOWN, out = UNKNOWN, out = UNKNOWN, 3368024598e40c84666cc311a42c256bbf880db3ac99sewardj out = seg1, out = UNKNOWN, out = NONPTR 3369024598e40c84666cc311a42c256bbf880db3ac99sewardj /*BINERROR("And32/And64")*/ 3370024598e40c84666cc311a42c256bbf880db3ac99sewardj ); 3371024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3372024598e40c84666cc311a42c256bbf880db3ac99sewardj out = ( looks_like_a_pointer(result) ? out : NONPTR ); 3373024598e40c84666cc311a42c256bbf880db3ac99sewardj return out; 3374024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3375024598e40c84666cc311a42c256bbf880db3ac99sewardj 3376024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3377024598e40c84666cc311a42c256bbf880db3ac99sewardj// `|`| n ? p 3378024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3379024598e40c84666cc311a42c256bbf880db3ac99sewardj// n | n ? p 3380024598e40c84666cc311a42c256bbf880db3ac99sewardj// ? | ? ? ? 3381024598e40c84666cc311a42c256bbf880db3ac99sewardj// p | p ? n 3382024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3383024598e40c84666cc311a42c256bbf880db3ac99sewardj/* It's OK to Or two pointers together, but the result definitely 3384024598e40c84666cc311a42c256bbf880db3ac99sewardj isn't a pointer. Why would you want to do that? Because of this: 3385024598e40c84666cc311a42c256bbf880db3ac99sewardj char* p1 = malloc(..); 3386024598e40c84666cc311a42c256bbf880db3ac99sewardj char* p2 = malloc(..); 3387024598e40c84666cc311a42c256bbf880db3ac99sewardj ... 3388024598e40c84666cc311a42c256bbf880db3ac99sewardj if (p1 || p2) { .. } 3389024598e40c84666cc311a42c256bbf880db3ac99sewardj In this case gcc on x86/amd64 quite literally or-s the two pointers 3390024598e40c84666cc311a42c256bbf880db3ac99sewardj together and throws away the result, the purpose of which is merely 3391024598e40c84666cc311a42c256bbf880db3ac99sewardj to sets %eflags.Z/%rflags.Z. So we have to allow it. 3392024598e40c84666cc311a42c256bbf880db3ac99sewardj*/ 3393024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result) 3394024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3395024598e40c84666cc311a42c256bbf880db3ac99sewardj Seg* out; 3396024598e40c84666cc311a42c256bbf880db3ac99sewardj BINOP( 3397024598e40c84666cc311a42c256bbf880db3ac99sewardj return BOTTOM, 3398024598e40c84666cc311a42c256bbf880db3ac99sewardj out = NONPTR, out = UNKNOWN, out = seg2, 3399024598e40c84666cc311a42c256bbf880db3ac99sewardj out = UNKNOWN, out = UNKNOWN, out = UNKNOWN, 3400024598e40c84666cc311a42c256bbf880db3ac99sewardj out = seg1, out = UNKNOWN, out = NONPTR 3401024598e40c84666cc311a42c256bbf880db3ac99sewardj ); 3402024598e40c84666cc311a42c256bbf880db3ac99sewardj out = ( looks_like_a_pointer(result) ? out : NONPTR ); 3403024598e40c84666cc311a42c256bbf880db3ac99sewardj return out; 3404024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3405024598e40c84666cc311a42c256bbf880db3ac99sewardj 3406024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3407024598e40c84666cc311a42c256bbf880db3ac99sewardj// ~ | n ? p 3408024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3409024598e40c84666cc311a42c256bbf880db3ac99sewardj// | n n n 3410024598e40c84666cc311a42c256bbf880db3ac99sewardj// ------------- 3411024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result) 3412024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3413024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3414024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg1); 3415024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3416024598e40c84666cc311a42c256bbf880db3ac99sewardj if (BOTTOM == seg1) return BOTTOM; 3417024598e40c84666cc311a42c256bbf880db3ac99sewardj return NONPTR; 3418024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3419024598e40c84666cc311a42c256bbf880db3ac99sewardj 3420024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pointers are rarely multiplied, but sometimes legitimately, eg. as hash 3421024598e40c84666cc311a42c256bbf880db3ac99sewardj// function inputs. But two pointers args --> error. 3422024598e40c84666cc311a42c256bbf880db3ac99sewardj// Pretend it always returns a nonptr. Maybe improve later. 3423024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2) 3424024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3425024598e40c84666cc311a42c256bbf880db3ac99sewardj# if SC_SEGS 3426024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg1); 3427024598e40c84666cc311a42c256bbf880db3ac99sewardj checkSeg(seg2); 3428024598e40c84666cc311a42c256bbf880db3ac99sewardj# endif 3429024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_known_segment(seg1) && is_known_segment(seg2)) 3430024598e40c84666cc311a42c256bbf880db3ac99sewardj h_record_arith_error(seg1, seg2, "Mul32/Mul64"); 3431024598e40c84666cc311a42c256bbf880db3ac99sewardj return NONPTR; 3432024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3433024598e40c84666cc311a42c256bbf880db3ac99sewardj 3434024598e40c84666cc311a42c256bbf880db3ac99sewardj 3435024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 3436024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Instrumentation ---*/ 3437024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 3438024598e40c84666cc311a42c256bbf880db3ac99sewardj 3439024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The h_ instrumenter that follows is complex, since it deals with 3440024598e40c84666cc311a42c256bbf880db3ac99sewardj shadow value computation. 3441024598e40c84666cc311a42c256bbf880db3ac99sewardj 3442024598e40c84666cc311a42c256bbf880db3ac99sewardj It also needs to generate instrumentation for the sg_ side of 3443024598e40c84666cc311a42c256bbf880db3ac99sewardj things. That's relatively straightforward. However, rather than 3444024598e40c84666cc311a42c256bbf880db3ac99sewardj confuse the code herein any further, we simply delegate the problem 3445024598e40c84666cc311a42c256bbf880db3ac99sewardj to sg_main.c, by using the four functions 3446024598e40c84666cc311a42c256bbf880db3ac99sewardj sg_instrument_{init,fini,IRStmt,final_jump}. These four completely 3447024598e40c84666cc311a42c256bbf880db3ac99sewardj abstractify the sg_ instrumentation. See comments in sg_main.c's 3448024598e40c84666cc311a42c256bbf880db3ac99sewardj instrumentation section for further details. */ 3449024598e40c84666cc311a42c256bbf880db3ac99sewardj 3450e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3451e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj/* Carries info about a particular tmp. The tmp's number is not 3452e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj recorded, as this is implied by (equal to) its index in the tmpMap 3453e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj in PCEnv. The tmp's type is also not recorded, as this is present 3454e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj in PCEnv.sb->tyenv. 3455e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3456e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj When .kind is NonShad, .shadow may give the identity of the temp 3457e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj currently holding the associated shadow value, or it may be 3458e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRTemp_INVALID if code to compute the shadow has not yet been 3459e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj emitted. 3460e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3461e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj When .kind is Shad tmp holds a shadow value, and so .shadow must be 3462e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRTemp_INVALID, since it is illogical for a shadow tmp itself to be 3463e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj shadowed. 3464e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj*/ 3465e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjtypedef 3466e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj enum { NonShad=1, Shad=2 } 3467e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempKind; 3468e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3469e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjtypedef 3470e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj struct { 3471e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempKind kind; 3472e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRTemp shadow; 3473e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj } 3474e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempMapEnt; 3475e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3476e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3477e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3478024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Carries around state during Ptrcheck instrumentation. */ 3479024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef 3480024598e40c84666cc311a42c256bbf880db3ac99sewardj struct { 3481024598e40c84666cc311a42c256bbf880db3ac99sewardj /* MODIFIED: the superblock being constructed. IRStmts are 3482024598e40c84666cc311a42c256bbf880db3ac99sewardj added. */ 3483e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRSB* sb; 3484024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool trace; 3485024598e40c84666cc311a42c256bbf880db3ac99sewardj 3486e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the 3487e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj current kind and possibly shadow temps for each temp in the 3488e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRSB being constructed. Note that it does not contain the 3489e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj type of each tmp. If you want to know the type, look at the 3490e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj relevant entry in sb->tyenv. It follows that at all times 3491e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj during the instrumentation process, the valid indices for 3492e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is 3493e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj total number of NonShad and Shad temps allocated so far. 3494e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3495e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj The reason for this strange split (types in one place, all 3496e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj other info in another) is that we need the types to be 3497e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj attached to sb so as to make it possible to do 3498e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the 3499e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj instrumentation process. 3500e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3501e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj Note that only integer temps of the guest word size are 3502e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj shadowed, since it is impossible (or meaningless) to hold a 3503e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj pointer in any other type of temp. */ 3504e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj XArray* /* of TempMapEnt */ qmpMap; 3505024598e40c84666cc311a42c256bbf880db3ac99sewardj 3506024598e40c84666cc311a42c256bbf880db3ac99sewardj /* READONLY: the host word type. Needed for constructing 3507024598e40c84666cc311a42c256bbf880db3ac99sewardj arguments of type 'HWord' to be passed to helper functions. 3508024598e40c84666cc311a42c256bbf880db3ac99sewardj Ity_I32 or Ity_I64 only. */ 3509024598e40c84666cc311a42c256bbf880db3ac99sewardj IRType hWordTy; 3510024598e40c84666cc311a42c256bbf880db3ac99sewardj 3511024598e40c84666cc311a42c256bbf880db3ac99sewardj /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */ 3512024598e40c84666cc311a42c256bbf880db3ac99sewardj IRType gWordTy; 3513024598e40c84666cc311a42c256bbf880db3ac99sewardj 3514024598e40c84666cc311a42c256bbf880db3ac99sewardj /* READONLY: the guest state size, so we can generate shadow 3515024598e40c84666cc311a42c256bbf880db3ac99sewardj offsets correctly. */ 3516024598e40c84666cc311a42c256bbf880db3ac99sewardj Int guest_state_sizeB; 3517024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3518024598e40c84666cc311a42c256bbf880db3ac99sewardj PCEnv; 3519024598e40c84666cc311a42c256bbf880db3ac99sewardj 3520024598e40c84666cc311a42c256bbf880db3ac99sewardj/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on 3521024598e40c84666cc311a42c256bbf880db3ac99sewardj demand), as they are encountered. This is for two reasons. 3522024598e40c84666cc311a42c256bbf880db3ac99sewardj 3523024598e40c84666cc311a42c256bbf880db3ac99sewardj (1) (less important reason): Many original tmps are unused due to 3524024598e40c84666cc311a42c256bbf880db3ac99sewardj initial IR optimisation, and we do not want to spaces in tables 3525024598e40c84666cc311a42c256bbf880db3ac99sewardj tracking them. 3526024598e40c84666cc311a42c256bbf880db3ac99sewardj 3527024598e40c84666cc311a42c256bbf880db3ac99sewardj Shadow IRTemps are therefore allocated on demand. pce.tmpMap is a 3528024598e40c84666cc311a42c256bbf880db3ac99sewardj table indexed [0 .. n_types-1], which gives the current shadow for 3529024598e40c84666cc311a42c256bbf880db3ac99sewardj each original tmp, or INVALID_IRTEMP if none is so far assigned. 3530024598e40c84666cc311a42c256bbf880db3ac99sewardj It is necessary to support making multiple assignments to a shadow 3531024598e40c84666cc311a42c256bbf880db3ac99sewardj -- specifically, after testing a shadow for definedness, it needs 3532024598e40c84666cc311a42c256bbf880db3ac99sewardj to be made defined. But IR's SSA property disallows this. 3533024598e40c84666cc311a42c256bbf880db3ac99sewardj 3534024598e40c84666cc311a42c256bbf880db3ac99sewardj (2) (more important reason): Therefore, when a shadow needs to get 3535024598e40c84666cc311a42c256bbf880db3ac99sewardj a new value, a new temporary is created, the value is assigned to 3536024598e40c84666cc311a42c256bbf880db3ac99sewardj that, and the tmpMap is updated to reflect the new binding. 3537024598e40c84666cc311a42c256bbf880db3ac99sewardj 3538024598e40c84666cc311a42c256bbf880db3ac99sewardj A corollary is that if the tmpMap maps a given tmp to 3539024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp_INVALID and we are hoping to read that shadow tmp, it means 3540024598e40c84666cc311a42c256bbf880db3ac99sewardj there's a read-before-write error in the original tmps. The IR 3541024598e40c84666cc311a42c256bbf880db3ac99sewardj sanity checker should catch all such anomalies, however. 3542024598e40c84666cc311a42c256bbf880db3ac99sewardj*/ 3543024598e40c84666cc311a42c256bbf880db3ac99sewardj 3544e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to 3545e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj both the table in pce->sb and to our auxiliary mapping. Note that 3546e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj newTemp may cause pce->tmpMap to resize, hence previous results 3547e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj from VG_(indexXA)(pce->tmpMap) are invalidated. */ 3548e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjstatic IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind ) 3549e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj{ 3550e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj Word newIx; 3551e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempMapEnt ent; 3552e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRTemp tmp = newIRTemp(pce->sb->tyenv, ty); 3553e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent.kind = kind; 3554e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent.shadow = IRTemp_INVALID; 3555e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj newIx = VG_(addToXA)( pce->qmpMap, &ent ); 3556e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(newIx == (Word)tmp); 3557e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj return tmp; 3558e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj} 3559e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3560024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Find the tmp currently shadowing the given original tmp. If none 3561024598e40c84666cc311a42c256bbf880db3ac99sewardj so far exists, allocate one. */ 3562024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig ) 3563024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3564e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempMapEnt* ent; 3565e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* VG_(indexXA) range-checks 'orig', hence no need to check 3566e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj here. */ 3567e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig ); 3568e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(ent->kind == NonShad); 3569e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj if (ent->shadow == IRTemp_INVALID) { 3570e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRTemp shadow = newTemp( pce, pce->gWordTy, Shad ); 3571e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* newTemp may cause pce->tmpMap to resize, hence previous results 3572e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj from VG_(indexXA) are invalid. */ 3573e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig ); 3574e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(ent->kind == NonShad); 3575e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(ent->shadow == IRTemp_INVALID); 3576e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent->shadow = shadow; 3577024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3578e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj return ent->shadow; 3579024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3580024598e40c84666cc311a42c256bbf880db3ac99sewardj 3581024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Allocate a new shadow for the given original tmp. This means any 3582024598e40c84666cc311a42c256bbf880db3ac99sewardj previous shadow is abandoned. This is needed because it is 3583024598e40c84666cc311a42c256bbf880db3ac99sewardj necessary to give a new value to a shadow once it has been tested 3584024598e40c84666cc311a42c256bbf880db3ac99sewardj for undefinedness, but unfortunately IR's SSA property disallows 3585024598e40c84666cc311a42c256bbf880db3ac99sewardj this. Instead we must abandon the old shadow, allocate a new one 3586e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj and use that instead. 3587e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 3588e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj This is the same as findShadowTmp, except we don't bother to see 3589e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj if a shadow temp already existed -- we simply allocate a new one 3590e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj regardless. */ 3591024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig ) 3592024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3593e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempMapEnt* ent; 3594e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* VG_(indexXA) range-checks 'orig', hence no need to check 3595e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj here. */ 3596e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig ); 3597e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(ent->kind == NonShad); 3598e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj if (1) { 3599e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRTemp shadow = newTemp( pce, pce->gWordTy, Shad ); 3600e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* newTemp may cause pce->tmpMap to resize, hence previous results 3601e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj from VG_(indexXA) are invalid. */ 3602e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig ); 3603e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(ent->kind == NonShad); 3604e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent->shadow = shadow; 3605e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj return shadow; 3606e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj } 3607e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* NOTREACHED */ 3608e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(0); 3609024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3610024598e40c84666cc311a42c256bbf880db3ac99sewardj 3611024598e40c84666cc311a42c256bbf880db3ac99sewardj 3612024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 3613024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- IRAtoms -- a subset of IRExprs ---*/ 3614024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 3615024598e40c84666cc311a42c256bbf880db3ac99sewardj 3616024598e40c84666cc311a42c256bbf880db3ac99sewardj/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by 3617024598e40c84666cc311a42c256bbf880db3ac99sewardj isIRAtom() in libvex_ir.h. Because this instrumenter expects flat 3618024598e40c84666cc311a42c256bbf880db3ac99sewardj input, most of this code deals in atoms. Usefully, a value atom 3619024598e40c84666cc311a42c256bbf880db3ac99sewardj always has a V-value which is also an atom: constants are shadowed 3620024598e40c84666cc311a42c256bbf880db3ac99sewardj by constants, and temps are shadowed by the corresponding shadow 3621024598e40c84666cc311a42c256bbf880db3ac99sewardj temporary. */ 3622024598e40c84666cc311a42c256bbf880db3ac99sewardj 3623024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef IRExpr IRAtom; 3624024598e40c84666cc311a42c256bbf880db3ac99sewardj 3625024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks 3626024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz like it's from original code? */ 3627024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 ) 3628024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 3629024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (a1->tag == Iex_Const) 3630024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 3631024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps) 3632024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 3633024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return False; 3634024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 3635024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 3636024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): is this an atom which looks 3637024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz like it's from shadow code? */ 3638024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 ) 3639024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 3640024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (a1->tag == Iex_Const) 3641024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 3642024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps) 3643024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 3644024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return False; 3645024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 3646024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz 3647024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz /* (used for sanity checks only): check that both args are atoms and 3648024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz are identically-kinded. */ 3649024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 ) 3650024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz { 3651024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp) 3652024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 3653024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz if (a1->tag == Iex_Const && a2->tag == Iex_Const) 3654024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return True; 3655024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz return False; 3656024598e40c84666cc311a42c256bbf880db3ac99sewardj//zz } 3657024598e40c84666cc311a42c256bbf880db3ac99sewardj 3658024598e40c84666cc311a42c256bbf880db3ac99sewardj 3659024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 3660024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Constructing IR fragments ---*/ 3661024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 3662024598e40c84666cc311a42c256bbf880db3ac99sewardj 3663024598e40c84666cc311a42c256bbf880db3ac99sewardj/* add stmt to a bb */ 3664024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) { 3665024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->trace) { 3666024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)(" %c: ", cat); 3667024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRStmt(st); 3668024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("\n"); 3669024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3670e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj addStmtToIRSB(pce->sb, st); 3671024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3672024598e40c84666cc311a42c256bbf880db3ac99sewardj 3673024598e40c84666cc311a42c256bbf880db3ac99sewardj/* assign value to tmp */ 3674024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic inline 3675024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) { 3676024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt(cat, pce, IRStmt_WrTmp(tmp,expr)); 3677024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3678024598e40c84666cc311a42c256bbf880db3ac99sewardj 3679024598e40c84666cc311a42c256bbf880db3ac99sewardj/* build various kinds of expressions */ 3680024598e40c84666cc311a42c256bbf880db3ac99sewardj#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2)) 3681024598e40c84666cc311a42c256bbf880db3ac99sewardj#define unop(_op, _arg) IRExpr_Unop((_op),(_arg)) 3682024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU8(_n) IRExpr_Const(IRConst_U8(_n)) 3683024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU16(_n) IRExpr_Const(IRConst_U16(_n)) 3684024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU32(_n) IRExpr_Const(IRConst_U32(_n)) 3685024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkU64(_n) IRExpr_Const(IRConst_U64(_n)) 3686024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkV128(_n) IRExpr_Const(IRConst_V128(_n)) 3687024598e40c84666cc311a42c256bbf880db3ac99sewardj#define mkexpr(_tmp) IRExpr_RdTmp((_tmp)) 3688024598e40c84666cc311a42c256bbf880db3ac99sewardj 3689024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Bind the given expression to a new temporary, and return the 3690024598e40c84666cc311a42c256bbf880db3ac99sewardj temporary. This effectively converts an arbitrary expression into 3691024598e40c84666cc311a42c256bbf880db3ac99sewardj an atom. 3692024598e40c84666cc311a42c256bbf880db3ac99sewardj 3693024598e40c84666cc311a42c256bbf880db3ac99sewardj 'ty' is the type of 'e' and hence the type that the new temporary 3694024598e40c84666cc311a42c256bbf880db3ac99sewardj needs to be. But passing it is redundant, since we can deduce the 3695024598e40c84666cc311a42c256bbf880db3ac99sewardj type merely by inspecting 'e'. So at least that fact to assert 3696024598e40c84666cc311a42c256bbf880db3ac99sewardj that the two types agree. */ 3697024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) { 3698024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp t; 3699e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRType tyE = typeOfIRExpr(pce->sb->tyenv, e); 3700024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(tyE == ty); /* so 'ty' is redundant (!) */ 3701e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj t = newTemp(pce, ty, Shad); 3702024598e40c84666cc311a42c256bbf880db3ac99sewardj assign(cat, pce, t, e); 3703024598e40c84666cc311a42c256bbf880db3ac99sewardj return mkexpr(t); 3704024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3705024598e40c84666cc311a42c256bbf880db3ac99sewardj 3706024598e40c84666cc311a42c256bbf880db3ac99sewardj 3707024598e40c84666cc311a42c256bbf880db3ac99sewardj 3708024598e40c84666cc311a42c256bbf880db3ac99sewardj//----------------------------------------------------------------------- 3709024598e40c84666cc311a42c256bbf880db3ac99sewardj// Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows. 3710024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3711024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/seg): 3712024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after modifying a word-sized value in/into a TempReg: 3713024598e40c84666cc311a42c256bbf880db3ac99sewardj// - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L 3714024598e40c84666cc311a42c256bbf880db3ac99sewardj// - BSWAP 3715024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3716024598e40c84666cc311a42c256bbf880db3ac99sewardj// Range check (NONPTR/UNKNOWN): 3717024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when introducing a new word-sized value into a TempReg: 3718024598e40c84666cc311a42c256bbf880db3ac99sewardj// - MOVL l, t2 3719024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3720024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying a word-sized value which lacks a corresponding segment 3721024598e40c84666cc311a42c256bbf880db3ac99sewardj// into a TempReg: 3722024598e40c84666cc311a42c256bbf880db3ac99sewardj// - straddled LDL 3723024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3724024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when a sub-word of a word (or two) is updated: 3725024598e40c84666cc311a42c256bbf880db3ac99sewardj// - SHROTL 3726024598e40c84666cc311a42c256bbf880db3ac99sewardj// - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB] 3727024598e40c84666cc311a42c256bbf880db3ac99sewardj// - PUT[WB] 3728024598e40c84666cc311a42c256bbf880db3ac99sewardj// - straddled STL (2 range checks) 3729024598e40c84666cc311a42c256bbf880db3ac99sewardj// - straddled STW (2 range checks) 3730024598e40c84666cc311a42c256bbf880db3ac99sewardj// - unstraddled STW 3731024598e40c84666cc311a42c256bbf880db3ac99sewardj// - STB 3732024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3733024598e40c84666cc311a42c256bbf880db3ac99sewardj// Just copy: 3734024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when copying word-sized values: 3735024598e40c84666cc311a42c256bbf880db3ac99sewardj// - MOVL t1, t2 (--optimise=no only) 3736024598e40c84666cc311a42c256bbf880db3ac99sewardj// - CMOV 3737024598e40c84666cc311a42c256bbf880db3ac99sewardj// - GETL, PUTL 3738024598e40c84666cc311a42c256bbf880db3ac99sewardj// - unstraddled LDL, unstraddled STL 3739024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3740024598e40c84666cc311a42c256bbf880db3ac99sewardj// - when barely changing 3741024598e40c84666cc311a42c256bbf880db3ac99sewardj// - INC[LWB]/DEC[LWB] 3742024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3743024598e40c84666cc311a42c256bbf880db3ac99sewardj// Set to NONPTR: 3744024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying a sub-word value into a TempReg: 3745024598e40c84666cc311a42c256bbf880db3ac99sewardj// - MOV[WB] l, t2 3746024598e40c84666cc311a42c256bbf880db3ac99sewardj// - GET[WB] 3747024598e40c84666cc311a42c256bbf880db3ac99sewardj// - unstraddled LDW 3748024598e40c84666cc311a42c256bbf880db3ac99sewardj// - straddled LDW 3749024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LDB 3750024598e40c84666cc311a42c256bbf880db3ac99sewardj// - POP[WB] 3751024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3752024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a TempReg: 3753024598e40c84666cc311a42c256bbf880db3ac99sewardj// - GETF 3754024598e40c84666cc311a42c256bbf880db3ac99sewardj// - CC2VAL 3755024598e40c84666cc311a42c256bbf880db3ac99sewardj// - POPL 3756024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3757024598e40c84666cc311a42c256bbf880db3ac99sewardj// - after copying an obvious non-ptr into a memory word: 3758024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU_W 3759024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3760024598e40c84666cc311a42c256bbf880db3ac99sewardj// Do nothing: 3761024598e40c84666cc311a42c256bbf880db3ac99sewardj// - LOCK, INCEIP 3762024598e40c84666cc311a42c256bbf880db3ac99sewardj// - WIDEN[WB] 3763024598e40c84666cc311a42c256bbf880db3ac99sewardj// - JMP, JIFZ 3764024598e40c84666cc311a42c256bbf880db3ac99sewardj// - CALLM_[SE], PUSHL, CALLM, CLEAR 3765024598e40c84666cc311a42c256bbf880db3ac99sewardj// - FPU, FPU_R (and similar MMX/SSE ones) 3766024598e40c84666cc311a42c256bbf880db3ac99sewardj// 3767024598e40c84666cc311a42c256bbf880db3ac99sewardj 3768024598e40c84666cc311a42c256bbf880db3ac99sewardj 3769024598e40c84666cc311a42c256bbf880db3ac99sewardj 3770024598e40c84666cc311a42c256bbf880db3ac99sewardj 3771024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Call h_fn (name h_nm) with the given arg, and return a new IRTemp 3772024598e40c84666cc311a42c256bbf880db3ac99sewardj holding the result. The arg must be a word-typed atom. Callee 3773024598e40c84666cc311a42c256bbf880db3ac99sewardj must be a VG_REGPARM(1) function. */ 3774024598e40c84666cc311a42c256bbf880db3ac99sewardj__attribute__((noinline)) 3775024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm, 3776024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1 ) 3777024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3778024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp res; 3779024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3780024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3781e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3782e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj res = newTemp(pce, pce->gWordTy, Shad); 3783024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_1_N( res, 1/*regparms*/, 3784024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3785024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_1( a1 ) ); 3786024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3787024598e40c84666cc311a42c256bbf880db3ac99sewardj return res; 3788024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3789024598e40c84666cc311a42c256bbf880db3ac99sewardj 3790024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Two-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(2) 3791024598e40c84666cc311a42c256bbf880db3ac99sewardj function.*/ 3792024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm, 3793024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2 ) 3794024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3795024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp res; 3796024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3797024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3798024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3799e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3800e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3801e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj res = newTemp(pce, pce->gWordTy, Shad); 3802024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_1_N( res, 2/*regparms*/, 3803024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3804024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_2( a1, a2 ) ); 3805024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3806024598e40c84666cc311a42c256bbf880db3ac99sewardj return res; 3807024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3808024598e40c84666cc311a42c256bbf880db3ac99sewardj 3809024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Three-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3) 3810024598e40c84666cc311a42c256bbf880db3ac99sewardj function.*/ 3811024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm, 3812024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 3813024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3814024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp res; 3815024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3816024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3817024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3818024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a3)); 3819e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3820e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3821e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy); 3822e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj res = newTemp(pce, pce->gWordTy, Shad); 3823024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_1_N( res, 3/*regparms*/, 3824024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3825024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_3( a1, a2, a3 ) ); 3826024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3827024598e40c84666cc311a42c256bbf880db3ac99sewardj return res; 3828024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3829024598e40c84666cc311a42c256bbf880db3ac99sewardj 3830024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Four-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3) 3831024598e40c84666cc311a42c256bbf880db3ac99sewardj function.*/ 3832024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm, 3833024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2, 3834024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a3, IRExpr* a4 ) 3835024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3836024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp res; 3837024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3838024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3839024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3840024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a3)); 3841024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a4)); 3842e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3843e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3844e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy); 3845e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy); 3846e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj res = newTemp(pce, pce->gWordTy, Shad); 3847024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_1_N( res, 3/*regparms*/, 3848024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3849024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_4( a1, a2, a3, a4 ) ); 3850024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3851024598e40c84666cc311a42c256bbf880db3ac99sewardj return res; 3852024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3853024598e40c84666cc311a42c256bbf880db3ac99sewardj 3854024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WW with no return value. Callee must be a 3855024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_REGPARM(2) function.*/ 3856024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WW ( PCEnv* pce, void* h_fn, HChar* h_nm, 3857024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2 ) 3858024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3859024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3860024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3861024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3862e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3863e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3864024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_0_N( 2/*regparms*/, 3865024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3866024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_2( a1, a2 ) ); 3867024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3868024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3869024598e40c84666cc311a42c256bbf880db3ac99sewardj 3870024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_W_WWW with no return value. Callee must be a 3871024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_REGPARM(3) function.*/ 3872024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm, 3873024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2, IRExpr* a3 ) 3874024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3875024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3876024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3877024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3878024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a3)); 3879e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3880e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3881e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy); 3882024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_0_N( 3/*regparms*/, 3883024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3884024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_3( a1, a2, a3 ) ); 3885024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3886024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3887024598e40c84666cc311a42c256bbf880db3ac99sewardj 3888024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 4 arguments. Callee must be a 3889024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_REGPARM(3) function.*/ 3890024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm, 3891024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2, 3892024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a3, IRExpr* a4 ) 3893024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3894024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3895024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3896024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3897024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a3)); 3898024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a4)); 3899e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3900e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3901e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy); 3902e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy); 3903024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_0_N( 3/*regparms*/, 3904024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3905024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_4( a1, a2, a3, a4 ) ); 3906024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3907024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3908024598e40c84666cc311a42c256bbf880db3ac99sewardj 3909024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Version of gen_dirty_v_WWW for 6 arguments. Callee must be a 3910024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_REGPARM(3) function.*/ 3911024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm, 3912024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2, IRExpr* a3, 3913024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a4, IRExpr* a5, IRExpr* a6 ) 3914024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3915024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 3916024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a1)); 3917024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a2)); 3918024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a3)); 3919024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a4)); 3920024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a5)); 3921024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a6)); 3922e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy); 3923e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy); 3924e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy); 3925e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy); 3926e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a5) == pce->gWordTy); 3927e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRExpr(pce->sb->tyenv, a6) == pce->gWordTy); 3928024598e40c84666cc311a42c256bbf880db3ac99sewardj di = unsafeIRDirty_0_N( 3/*regparms*/, 3929024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm, VG_(fnptr_to_fnentry)( h_fn ), 3930024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) ); 3931024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Dirty(di) ); 3932024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3933024598e40c84666cc311a42c256bbf880db3ac99sewardj 3934024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a ) 3935024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3936e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRType a_ty = typeOfIRExpr(pce->sb->tyenv, a); 3937024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(a)); 3938024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->hWordTy == Ity_I32) { 3939024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (a_ty) { 3940024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I8: 3941024598e40c84666cc311a42c256bbf880db3ac99sewardj return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) ); 3942024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I16: 3943024598e40c84666cc311a42c256bbf880db3ac99sewardj return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) ); 3944024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 3945024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRType(a_ty); 3946024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 3947024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3948024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3949024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(pce->hWordTy == Ity_I64); 3950024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (a_ty) { 3951024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I8: 3952024598e40c84666cc311a42c256bbf880db3ac99sewardj return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) ); 3953024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I16: 3954024598e40c84666cc311a42c256bbf880db3ac99sewardj return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) ); 3955024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I32: 3956024598e40c84666cc311a42c256bbf880db3ac99sewardj return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) ); 3957024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 3958024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRType(a_ty); 3959024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 3960024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3961024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3962024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3963024598e40c84666cc311a42c256bbf880db3ac99sewardj 3964024598e40c84666cc311a42c256bbf880db3ac99sewardj/* 'e' is a word-sized atom. Call nonptr_or_unknown with it, bind the 3965024598e40c84666cc311a42c256bbf880db3ac99sewardj results to a new temporary, and return the temporary. Note this 3966024598e40c84666cc311a42c256bbf880db3ac99sewardj takes an original expression but returns a shadow value. */ 3967024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e ) 3968024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3969024598e40c84666cc311a42c256bbf880db3ac99sewardj return gen_dirty_W_W( pce, &nonptr_or_unknown, 3970024598e40c84666cc311a42c256bbf880db3ac99sewardj "nonptr_or_unknown", e ); 3971024598e40c84666cc311a42c256bbf880db3ac99sewardj} 3972024598e40c84666cc311a42c256bbf880db3ac99sewardj 3973024598e40c84666cc311a42c256bbf880db3ac99sewardj 3974024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Generate the shadow value for an IRExpr which is an atom and 3975024598e40c84666cc311a42c256bbf880db3ac99sewardj guaranteed to be word-sized. */ 3976024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e ) 3977024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 3978024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->gWordTy == Ity_I32) { 3979024598e40c84666cc311a42c256bbf880db3ac99sewardj if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) { 3980024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp t; 3981024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 4); 3982024598e40c84666cc311a42c256bbf880db3ac99sewardj t = gen_call_nonptr_or_unknown_w(pce, e); 3983024598e40c84666cc311a42c256bbf880db3ac99sewardj return mkexpr(t); 3984024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3985024598e40c84666cc311a42c256bbf880db3ac99sewardj if (e->tag == Iex_RdTmp 3986e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj && typeOfIRExpr(pce->sb->tyenv, e) == Ity_I32) { 3987024598e40c84666cc311a42c256bbf880db3ac99sewardj return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) ); 3988024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3989024598e40c84666cc311a42c256bbf880db3ac99sewardj /* there are no other word-sized atom cases */ 3990024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 3991024598e40c84666cc311a42c256bbf880db3ac99sewardj if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) { 3992024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp t; 3993024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == 8); 3994024598e40c84666cc311a42c256bbf880db3ac99sewardj //return mkU64( (ULong)(UWord)NONPTR ); 3995024598e40c84666cc311a42c256bbf880db3ac99sewardj t = gen_call_nonptr_or_unknown_w(pce, e); 3996024598e40c84666cc311a42c256bbf880db3ac99sewardj return mkexpr(t); 3997024598e40c84666cc311a42c256bbf880db3ac99sewardj } 3998024598e40c84666cc311a42c256bbf880db3ac99sewardj if (e->tag == Iex_RdTmp 3999e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj && typeOfIRExpr(pce->sb->tyenv, e) == Ity_I64) { 4000024598e40c84666cc311a42c256bbf880db3ac99sewardj return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) ); 4001024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4002024598e40c84666cc311a42c256bbf880db3ac99sewardj /* there are no other word-sized atom cases */ 4003024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4004024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRExpr(e); 4005024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 4006024598e40c84666cc311a42c256bbf880db3ac99sewardj} 4007024598e40c84666cc311a42c256bbf880db3ac99sewardj 4008024598e40c84666cc311a42c256bbf880db3ac99sewardj 4009024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic 4010024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid instrument_arithop ( PCEnv* pce, 4011024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp dst, /* already holds result */ 4012024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp dstv, /* generate an assignment to this */ 4013024598e40c84666cc311a42c256bbf880db3ac99sewardj IROp op, 4014024598e40c84666cc311a42c256bbf880db3ac99sewardj /* original args, guaranteed to be atoms */ 4015024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 ) 4016024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 4017024598e40c84666cc311a42c256bbf880db3ac99sewardj HChar* nm = NULL; 4018024598e40c84666cc311a42c256bbf880db3ac99sewardj void* fn = NULL; 4019024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a1v = NULL; 4020024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* a2v = NULL; 4021024598e40c84666cc311a42c256bbf880db3ac99sewardj //IRExpr* a3v = NULL; 4022024598e40c84666cc311a42c256bbf880db3ac99sewardj //IRExpr* a4v = NULL; 4023024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp res = IRTemp_INVALID; 4024024598e40c84666cc311a42c256bbf880db3ac99sewardj 4025024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->gWordTy == Ity_I32) { 4026024598e40c84666cc311a42c256bbf880db3ac99sewardj 4027024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(pce->hWordTy == Ity_I32); 4028024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (op) { 4029024598e40c84666cc311a42c256bbf880db3ac99sewardj 4030024598e40c84666cc311a42c256bbf880db3ac99sewardj /* For these cases, pass Segs for both arguments, and the 4031024598e40c84666cc311a42c256bbf880db3ac99sewardj result value. */ 4032024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32; 4033024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32; 4034024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Or32: nm = "do_orW"; fn = &do_orW; goto ssr32; 4035024598e40c84666cc311a42c256bbf880db3ac99sewardj ssr32: 4036024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4037024598e40c84666cc311a42c256bbf880db3ac99sewardj a2v = schemeEw_Atom( pce, a2 ); 4038024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) ); 4039024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4040024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4041024598e40c84666cc311a42c256bbf880db3ac99sewardj 4042024598e40c84666cc311a42c256bbf880db3ac99sewardj /* In this case, pass Segs for both arguments, the result 4043024598e40c84666cc311a42c256bbf880db3ac99sewardj value, and the difference between the (original) values of 4044024598e40c84666cc311a42c256bbf880db3ac99sewardj the arguments. */ 4045024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_And32: 4046024598e40c84666cc311a42c256bbf880db3ac99sewardj nm = "do_andW"; fn = &do_andW; 4047024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4048024598e40c84666cc311a42c256bbf880db3ac99sewardj a2v = schemeEw_Atom( pce, a2 ); 4049024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WWWW( 4050024598e40c84666cc311a42c256bbf880db3ac99sewardj pce, fn, nm, a1v, a2v, mkexpr(dst), 4051024598e40c84666cc311a42c256bbf880db3ac99sewardj assignNew( 'I', pce, Ity_I32, 4052024598e40c84666cc311a42c256bbf880db3ac99sewardj binop(Iop_Sub32,a1,a2) ) ); 4053024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4054024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4055024598e40c84666cc311a42c256bbf880db3ac99sewardj 4056024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Pass one shadow arg and the result to the helper. */ 4057024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32; 4058024598e40c84666cc311a42c256bbf880db3ac99sewardj vr32: 4059024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4060024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) ); 4061024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4062024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4063024598e40c84666cc311a42c256bbf880db3ac99sewardj 4064024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Pass two shadow args only to the helper. */ 4065024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32; 4066024598e40c84666cc311a42c256bbf880db3ac99sewardj vv32: 4067024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4068024598e40c84666cc311a42c256bbf880db3ac99sewardj a2v = schemeEw_Atom( pce, a2 ); 4069024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v ); 4070024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4071024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4072024598e40c84666cc311a42c256bbf880db3ac99sewardj 4073024598e40c84666cc311a42c256bbf880db3ac99sewardj /* We don't really know what the result could be; test at run 4074024598e40c84666cc311a42c256bbf880db3ac99sewardj time. */ 4075024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_64HIto32: goto n_or_u_32; 4076024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_64to32: goto n_or_u_32; 4077024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Xor32: goto n_or_u_32; 4078024598e40c84666cc311a42c256bbf880db3ac99sewardj n_or_u_32: 4079024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4080024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr( 4081024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_call_nonptr_or_unknown_w( pce, 4082024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr(dst) ) ) ); 4083024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4084024598e40c84666cc311a42c256bbf880db3ac99sewardj 4085024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Cases where it's very obvious that the result cannot be a 4086024598e40c84666cc311a42c256bbf880db3ac99sewardj pointer. Hence declare directly that it's NONPTR; don't 4087024598e40c84666cc311a42c256bbf880db3ac99sewardj bother with the overhead of calling nonptr_or_unknown. */ 4088024598e40c84666cc311a42c256bbf880db3ac99sewardj 4089024598e40c84666cc311a42c256bbf880db3ac99sewardj /* cases where it makes no sense for the result to be a ptr */ 4090024598e40c84666cc311a42c256bbf880db3ac99sewardj /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd 4091024598e40c84666cc311a42c256bbf880db3ac99sewardj arg, so that shift by zero preserves the original 4092024598e40c84666cc311a42c256bbf880db3ac99sewardj value. */ 4093024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Shl32: goto n32; 4094024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Sar32: goto n32; 4095024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Shr32: goto n32; 4096024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_16Uto32: goto n32; 4097024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_16Sto32: goto n32; 4098024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_F64toI32: goto n32; 4099024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_16HLto32: goto n32; 4100024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_MullS16: goto n32; 4101024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_MullU16: goto n32; 4102024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_PRemC3210F64: goto n32; 4103024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_DivU32: goto n32; 4104024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_DivS32: goto n32; 4105024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_V128to32: goto n32; 4106024598e40c84666cc311a42c256bbf880db3ac99sewardj 4107024598e40c84666cc311a42c256bbf880db3ac99sewardj /* cases where result range is very limited and clearly cannot 4108024598e40c84666cc311a42c256bbf880db3ac99sewardj be a pointer */ 4109024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_1Uto32: goto n32; 4110024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_1Sto32: goto n32; 4111024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_8Uto32: goto n32; 4112024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_8Sto32: goto n32; 4113024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Clz32: goto n32; 4114024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Ctz32: goto n32; 4115024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpF64: goto n32; 4116024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpORD32S: goto n32; 4117024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpORD32U: goto n32; 4118024598e40c84666cc311a42c256bbf880db3ac99sewardj n32: 4119024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkU32( (UWord)NONPTR )); 4120024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4121024598e40c84666cc311a42c256bbf880db3ac99sewardj 4122024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 4123024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("instrument_arithop(32-bit): unhandled: "); 4124024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIROp(op); 4125024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 4126024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4127024598e40c84666cc311a42c256bbf880db3ac99sewardj 4128024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4129024598e40c84666cc311a42c256bbf880db3ac99sewardj 4130024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(pce->gWordTy == Ity_I64); 4131024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (op) { 4132024598e40c84666cc311a42c256bbf880db3ac99sewardj 4133024598e40c84666cc311a42c256bbf880db3ac99sewardj /* For these cases, pass Segs for both arguments, and the 4134024598e40c84666cc311a42c256bbf880db3ac99sewardj result value. */ 4135024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64; 4136024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64; 4137024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Or64: nm = "do_orW"; fn = &do_orW; goto ssr64; 4138024598e40c84666cc311a42c256bbf880db3ac99sewardj ssr64: 4139024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4140024598e40c84666cc311a42c256bbf880db3ac99sewardj a2v = schemeEw_Atom( pce, a2 ); 4141024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) ); 4142024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4143024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4144024598e40c84666cc311a42c256bbf880db3ac99sewardj 4145024598e40c84666cc311a42c256bbf880db3ac99sewardj /* In this case, pass Segs for both arguments, the result 4146024598e40c84666cc311a42c256bbf880db3ac99sewardj value, and the difference between the (original) values of 4147024598e40c84666cc311a42c256bbf880db3ac99sewardj the arguments. */ 4148024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_And64: 4149024598e40c84666cc311a42c256bbf880db3ac99sewardj nm = "do_andW"; fn = &do_andW; 4150024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4151024598e40c84666cc311a42c256bbf880db3ac99sewardj a2v = schemeEw_Atom( pce, a2 ); 4152024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WWWW( 4153024598e40c84666cc311a42c256bbf880db3ac99sewardj pce, fn, nm, a1v, a2v, mkexpr(dst), 4154024598e40c84666cc311a42c256bbf880db3ac99sewardj assignNew( 'I', pce, Ity_I64, 4155024598e40c84666cc311a42c256bbf880db3ac99sewardj binop(Iop_Sub64,a1,a2) ) ); 4156024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4157024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4158024598e40c84666cc311a42c256bbf880db3ac99sewardj 4159024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Pass one shadow arg and the result to the helper. */ 4160024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64; 4161024598e40c84666cc311a42c256bbf880db3ac99sewardj vr64: 4162024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4163024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) ); 4164024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4165024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4166024598e40c84666cc311a42c256bbf880db3ac99sewardj 4167024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Pass two shadow args only to the helper. */ 4168024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64; 4169024598e40c84666cc311a42c256bbf880db3ac99sewardj vv64: 4170024598e40c84666cc311a42c256bbf880db3ac99sewardj a1v = schemeEw_Atom( pce, a1 ); 4171024598e40c84666cc311a42c256bbf880db3ac99sewardj a2v = schemeEw_Atom( pce, a2 ); 4172024598e40c84666cc311a42c256bbf880db3ac99sewardj res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v ); 4173024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkexpr(res) ); 4174024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4175024598e40c84666cc311a42c256bbf880db3ac99sewardj 4176024598e40c84666cc311a42c256bbf880db3ac99sewardj /* We don't really know what the result could be; test at run 4177024598e40c84666cc311a42c256bbf880db3ac99sewardj time. */ 4178024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Xor64: goto n_or_u_64; 4179024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_128HIto64: goto n_or_u_64; 4180024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_128to64: goto n_or_u_64; 4181024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_V128HIto64: goto n_or_u_64; 4182024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_V128to64: goto n_or_u_64; 4183024598e40c84666cc311a42c256bbf880db3ac99sewardj n_or_u_64: 4184024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4185024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr( 4186024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_call_nonptr_or_unknown_w( pce, 4187024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr(dst) ) ) ); 4188024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4189024598e40c84666cc311a42c256bbf880db3ac99sewardj 4190024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Cases where it's very obvious that the result cannot be a 4191024598e40c84666cc311a42c256bbf880db3ac99sewardj pointer. Hence declare directly that it's NONPTR; don't 4192024598e40c84666cc311a42c256bbf880db3ac99sewardj bother with the overhead of calling nonptr_or_unknown. */ 4193024598e40c84666cc311a42c256bbf880db3ac99sewardj 4194024598e40c84666cc311a42c256bbf880db3ac99sewardj /* cases where it makes no sense for the result to be a ptr */ 4195024598e40c84666cc311a42c256bbf880db3ac99sewardj /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd 4196024598e40c84666cc311a42c256bbf880db3ac99sewardj arg, so that shift by zero preserves the original 4197024598e40c84666cc311a42c256bbf880db3ac99sewardj value. */ 4198024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Shl64: goto n64; 4199024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Sar64: goto n64; 4200024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Shr64: goto n64; 4201024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_32Uto64: goto n64; 4202024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_32Sto64: goto n64; 4203024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_16Uto64: goto n64; 4204024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_16Sto64: goto n64; 4205024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_32HLto64: goto n64; 4206024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_DivModU64to32: goto n64; 4207024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_DivModS64to32: goto n64; 4208024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_F64toI64: goto n64; 4209024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_MullS32: goto n64; 4210024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_MullU32: goto n64; 4211024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_DivU64: goto n64; 4212024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_DivS64: goto n64; 4213024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_ReinterpF64asI64: goto n64; 4214024598e40c84666cc311a42c256bbf880db3ac99sewardj 4215024598e40c84666cc311a42c256bbf880db3ac99sewardj /* cases where result range is very limited and clearly cannot 4216024598e40c84666cc311a42c256bbf880db3ac99sewardj be a pointer */ 4217024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_1Uto64: goto n64; 4218024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_8Uto64: goto n64; 4219024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_8Sto64: goto n64; 4220024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Ctz64: goto n64; 4221024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Clz64: goto n64; 4222024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpORD64S: goto n64; 4223024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpORD64U: goto n64; 4224024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 64-bit simd */ 4225024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Avg8Ux8: case Iop_Avg16Ux4: 4226024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4: 4227024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Min8Ux8: case Iop_MulHi16Ux4: 4228024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4: 4229024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2: 4230024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8: 4231024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8: 4232024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8: 4233024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4: 4234024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4: 4235024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2: 4236024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2: 4237024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8: 4238024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8: 4239024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4: 4240024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2: 4241024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_InterleaveLO16x4: case Iop_SarN8x8: 4242024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2: 4243024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4: 4244024598e40c84666cc311a42c256bbf880db3ac99sewardj n64: 4245024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkU64( (UWord)NONPTR )); 4246024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4247024598e40c84666cc311a42c256bbf880db3ac99sewardj 4248024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 4249024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("instrument_arithop(64-bit): unhandled: "); 4250024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIROp(op); 4251024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 4252024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4253024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4254024598e40c84666cc311a42c256bbf880db3ac99sewardj} 4255024598e40c84666cc311a42c256bbf880db3ac99sewardj 4256024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic 4257024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid gen_call_nonptr_or_unknown_range ( PCEnv* pce, 4258024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* addr, IRAtom* len ) 4259024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 4260024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WW( pce, 4261024598e40c84666cc311a42c256bbf880db3ac99sewardj &nonptr_or_unknown_range, 4262024598e40c84666cc311a42c256bbf880db3ac99sewardj "nonptr_or_unknown_range", 4263024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, len ); 4264024598e40c84666cc311a42c256bbf880db3ac99sewardj} 4265024598e40c84666cc311a42c256bbf880db3ac99sewardj 4266024598e40c84666cc311a42c256bbf880db3ac99sewardj/* iii describes zero or more non-exact integer register updates. For 4267024598e40c84666cc311a42c256bbf880db3ac99sewardj each one, generate IR to get the containing register, apply 4268024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown to it, and write it back again. */ 4269024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii ) 4270024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 4271024598e40c84666cc311a42c256bbf880db3ac99sewardj Int i; 4272024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(iii && iii->n_offsets >= 0); 4273024598e40c84666cc311a42c256bbf880db3ac99sewardj for (i = 0; i < iii->n_offsets; i++) { 4274024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy, 4275024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr_Get( iii->offsets[i], pce->gWordTy )); 4276024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 ); 4277024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Put( iii->offsets[i] 4278024598e40c84666cc311a42c256bbf880db3ac99sewardj + pce->guest_state_sizeB, 4279024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr(a2) )); 4280024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4281024598e40c84666cc311a42c256bbf880db3ac99sewardj} 4282024598e40c84666cc311a42c256bbf880db3ac99sewardj 42831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj/* Generate into 'pce', instrumentation for 'st'. Also copy 'st' 42841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj itself into 'pce' (the caller does not do so). This is somewhat 4285024598e40c84666cc311a42c256bbf880db3ac99sewardj complex and relies heavily on the assumption that the incoming IR 4286024598e40c84666cc311a42c256bbf880db3ac99sewardj is in flat form. 4287024598e40c84666cc311a42c256bbf880db3ac99sewardj 4288024598e40c84666cc311a42c256bbf880db3ac99sewardj Generally speaking, the instrumentation is placed after the 4289024598e40c84666cc311a42c256bbf880db3ac99sewardj original statement, so that results computed by the original can be 4290024598e40c84666cc311a42c256bbf880db3ac99sewardj used in the instrumentation. However, that isn't safe for memory 4291024598e40c84666cc311a42c256bbf880db3ac99sewardj references, since we need the instrumentation (hence bounds check 4292024598e40c84666cc311a42c256bbf880db3ac99sewardj and potential error message) to happen before the reference itself, 4293024598e40c84666cc311a42c256bbf880db3ac99sewardj as the latter could cause a fault. */ 4294024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic void schemeS ( PCEnv* pce, IRStmt* st ) 4295024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 4296024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(st); 4297024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isFlatIRStmt(st)); 4298024598e40c84666cc311a42c256bbf880db3ac99sewardj 4299024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (st->tag) { 4300024598e40c84666cc311a42c256bbf880db3ac99sewardj 4301024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_Dirty: { 4302024598e40c84666cc311a42c256bbf880db3ac99sewardj Int i; 4303024598e40c84666cc311a42c256bbf880db3ac99sewardj IRDirty* di; 4304024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4305024598e40c84666cc311a42c256bbf880db3ac99sewardj /* nasty. assumes that (1) all helpers are unconditional, 4306024598e40c84666cc311a42c256bbf880db3ac99sewardj and (2) all outputs are non-ptr */ 4307024598e40c84666cc311a42c256bbf880db3ac99sewardj di = st->Ist.Dirty.details; 4308024598e40c84666cc311a42c256bbf880db3ac99sewardj /* deal with the return tmp, if any */ 4309024598e40c84666cc311a42c256bbf880db3ac99sewardj if (di->tmp != IRTemp_INVALID 4310e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj && typeOfIRTemp(pce->sb->tyenv, di->tmp) == pce->gWordTy) { 4311024598e40c84666cc311a42c256bbf880db3ac99sewardj /* di->tmp is shadowed. Set it to NONPTR. */ 4312024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp dstv = newShadowTmp( pce, di->tmp ); 4313024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->gWordTy == Ity_I32) { 4314024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkU32( (UWord)NONPTR )); 4315024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4316024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkU64( (UWord)NONPTR )); 4317024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4318024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4319024598e40c84666cc311a42c256bbf880db3ac99sewardj /* apply the nonptr_or_unknown technique to any parts of 4320024598e40c84666cc311a42c256bbf880db3ac99sewardj the guest state that happen to get written */ 4321024598e40c84666cc311a42c256bbf880db3ac99sewardj for (i = 0; i < di->nFxState; i++) { 4322024598e40c84666cc311a42c256bbf880db3ac99sewardj IntRegInfo iii; 4323024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(di->fxState[i].fx != Ifx_None); 4324024598e40c84666cc311a42c256bbf880db3ac99sewardj if (di->fxState[i].fx == Ifx_Read) 4325024598e40c84666cc311a42c256bbf880db3ac99sewardj continue; /* this bit is only read -- not interesting */ 4326024598e40c84666cc311a42c256bbf880db3ac99sewardj get_IntRegInfo( &iii, di->fxState[i].offset, 4327024598e40c84666cc311a42c256bbf880db3ac99sewardj di->fxState[i].size ); 4328024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(iii.n_offsets >= -1 4329024598e40c84666cc311a42c256bbf880db3ac99sewardj && iii.n_offsets <= N_INTREGINFO_OFFSETS); 4330024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Deal with 3 possible cases, same as with Ist_Put 4331024598e40c84666cc311a42c256bbf880db3ac99sewardj elsewhere in this function. */ 4332024598e40c84666cc311a42c256bbf880db3ac99sewardj if (iii.n_offsets == -1) { 4333024598e40c84666cc311a42c256bbf880db3ac99sewardj /* case (1): exact write of an integer register. */ 4334024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* a1 4335024598e40c84666cc311a42c256bbf880db3ac99sewardj = assignNew( 'I', pce, pce->gWordTy, 4336024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr_Get( iii.offsets[i], pce->gWordTy )); 4337024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 ); 4338024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, IRStmt_Put( iii.offsets[i] 4339024598e40c84666cc311a42c256bbf880db3ac99sewardj + pce->guest_state_sizeB, 4340024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr(a2) )); 4341024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4342024598e40c84666cc311a42c256bbf880db3ac99sewardj /* when == 0: case (3): no instrumentation needed */ 4343024598e40c84666cc311a42c256bbf880db3ac99sewardj /* when > 0: case (2) .. complex case. Fish out the 4344024598e40c84666cc311a42c256bbf880db3ac99sewardj stored value for the whole register, heave it 4345024598e40c84666cc311a42c256bbf880db3ac99sewardj through nonptr_or_unknown, and use that as the new 4346024598e40c84666cc311a42c256bbf880db3ac99sewardj shadow value. */ 4347024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(iii.n_offsets >= 0 4348024598e40c84666cc311a42c256bbf880db3ac99sewardj && iii.n_offsets <= N_INTREGINFO_OFFSETS); 4349024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_nonptr_or_unknown_for_III( pce, &iii ); 4350024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4351024598e40c84666cc311a42c256bbf880db3ac99sewardj } /* for (i = 0; i < di->nFxState; i++) */ 4352024598e40c84666cc311a42c256bbf880db3ac99sewardj /* finally, deal with memory outputs */ 4353024598e40c84666cc311a42c256bbf880db3ac99sewardj if (di->mFx != Ifx_None) { 4354024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(di->mAddr && isIRAtom(di->mAddr)); 4355024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(di->mSize > 0); 4356024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_call_nonptr_or_unknown_range( pce, di->mAddr, 4357024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRExpr_HWord(di->mSize)); 4358024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4359024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4360024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4361024598e40c84666cc311a42c256bbf880db3ac99sewardj 4362024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_NoOp: 4363024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4364024598e40c84666cc311a42c256bbf880db3ac99sewardj 4365024598e40c84666cc311a42c256bbf880db3ac99sewardj /* nothing interesting in these; just copy them through */ 4366024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_AbiHint: 4367024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_MBE: 4368024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_Exit: 4369024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_IMark: 4370024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4371024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4372024598e40c84666cc311a42c256bbf880db3ac99sewardj 4373024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_PutI: { 4374024598e40c84666cc311a42c256bbf880db3ac99sewardj IRRegArray* descr = st->Ist.PutI.descr; 4375024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4376024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(descr && descr->elemTy); 4377024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_integer_guest_reg_array(descr)) { 4378024598e40c84666cc311a42c256bbf880db3ac99sewardj /* if this fails, is_integer_guest_reg_array is returning 4379024598e40c84666cc311a42c256bbf880db3ac99sewardj bogus results */ 4380024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(descr->elemTy == pce->gWordTy); 4381024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 4382024598e40c84666cc311a42c256bbf880db3ac99sewardj 'I', pce, 4383024598e40c84666cc311a42c256bbf880db3ac99sewardj IRStmt_PutI( 4384024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRRegArray(descr->base + pce->guest_state_sizeB, 4385024598e40c84666cc311a42c256bbf880db3ac99sewardj descr->elemTy, descr->nElems), 4386024598e40c84666cc311a42c256bbf880db3ac99sewardj st->Ist.PutI.ix, 4387024598e40c84666cc311a42c256bbf880db3ac99sewardj st->Ist.PutI.bias, 4388024598e40c84666cc311a42c256bbf880db3ac99sewardj schemeEw_Atom( pce, st->Ist.PutI.data) 4389024598e40c84666cc311a42c256bbf880db3ac99sewardj ) 4390024598e40c84666cc311a42c256bbf880db3ac99sewardj ); 4391024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4392024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4393024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4394024598e40c84666cc311a42c256bbf880db3ac99sewardj 4395024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_Put: { 4396024598e40c84666cc311a42c256bbf880db3ac99sewardj /* PUT(offset) = atom */ 4397024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 3 cases: 4398024598e40c84666cc311a42c256bbf880db3ac99sewardj 1. It's a complete write of an integer register. Get hold of 4399024598e40c84666cc311a42c256bbf880db3ac99sewardj 'atom's shadow value and write it in the shadow state. 4400024598e40c84666cc311a42c256bbf880db3ac99sewardj 2. It's a partial write of an integer register. Let the write 4401024598e40c84666cc311a42c256bbf880db3ac99sewardj happen, then fish out the complete register value and see if, 4402024598e40c84666cc311a42c256bbf880db3ac99sewardj via range checking, consultation of tea leaves, etc, its 4403024598e40c84666cc311a42c256bbf880db3ac99sewardj shadow value can be upgraded to anything useful. 4404024598e40c84666cc311a42c256bbf880db3ac99sewardj 3. It is none of the above. Generate no instrumentation. */ 4405024598e40c84666cc311a42c256bbf880db3ac99sewardj IntRegInfo iii; 4406024598e40c84666cc311a42c256bbf880db3ac99sewardj IRType ty; 4407024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4408e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ty = typeOfIRExpr(pce->sb->tyenv, st->Ist.Put.data); 4409024598e40c84666cc311a42c256bbf880db3ac99sewardj get_IntRegInfo( &iii, st->Ist.Put.offset, 4410024598e40c84666cc311a42c256bbf880db3ac99sewardj sizeofIRType(ty) ); 4411024598e40c84666cc311a42c256bbf880db3ac99sewardj if (iii.n_offsets == -1) { 4412024598e40c84666cc311a42c256bbf880db3ac99sewardj /* case (1): exact write of an integer register. */ 4413024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(ty == pce->gWordTy); 4414024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'I', pce, 4415024598e40c84666cc311a42c256bbf880db3ac99sewardj IRStmt_Put( st->Ist.Put.offset 4416024598e40c84666cc311a42c256bbf880db3ac99sewardj + pce->guest_state_sizeB, 4417024598e40c84666cc311a42c256bbf880db3ac99sewardj schemeEw_Atom( pce, st->Ist.Put.data)) ); 4418024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4419024598e40c84666cc311a42c256bbf880db3ac99sewardj /* when == 0: case (3): no instrumentation needed */ 4420024598e40c84666cc311a42c256bbf880db3ac99sewardj /* when > 0: case (2) .. complex case. Fish out the 4421024598e40c84666cc311a42c256bbf880db3ac99sewardj stored value for the whole register, heave it through 4422024598e40c84666cc311a42c256bbf880db3ac99sewardj nonptr_or_unknown, and use that as the new shadow 4423024598e40c84666cc311a42c256bbf880db3ac99sewardj value. */ 4424024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(iii.n_offsets >= 0 4425024598e40c84666cc311a42c256bbf880db3ac99sewardj && iii.n_offsets <= N_INTREGINFO_OFFSETS); 4426024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_nonptr_or_unknown_for_III( pce, &iii ); 4427024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4428024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4429024598e40c84666cc311a42c256bbf880db3ac99sewardj } /* case Ist_Put */ 4430024598e40c84666cc311a42c256bbf880db3ac99sewardj 4431024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_Store: { 4432024598e40c84666cc311a42c256bbf880db3ac99sewardj /* We have: STle(addr) = data 4433024598e40c84666cc311a42c256bbf880db3ac99sewardj if data is int-word sized, do 4434024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store4(addr, addr#, data, data#) 4435024598e40c84666cc311a42c256bbf880db3ac99sewardj for all other stores 4436024598e40c84666cc311a42c256bbf880db3ac99sewardj check_store{1,2}(addr, addr#, data) 4437024598e40c84666cc311a42c256bbf880db3ac99sewardj 4438024598e40c84666cc311a42c256bbf880db3ac99sewardj The helper actually *does* the store, so that it can do 4439024598e40c84666cc311a42c256bbf880db3ac99sewardj the post-hoc ugly hack of inspecting and "improving" the 4440024598e40c84666cc311a42c256bbf880db3ac99sewardj shadow data after the store, in the case where it isn't an 4441024598e40c84666cc311a42c256bbf880db3ac99sewardj aligned word store. 44421c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj 44431c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj Only word-sized values are shadowed. If this is a 44441c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj store-conditional, .resSC will denote a non-word-typed 44451c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj temp, and so we don't need to shadow it. Assert about the 44461c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj type, tho. However, since we're not re-emitting the 44471c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj original IRStmt_Store, but rather doing it as part of the 44481c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj helper function, we need to actually do a SC in the 44491c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj helper, and assign the result bit to .resSC. Ugly. 4450024598e40c84666cc311a42c256bbf880db3ac99sewardj */ 4451024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* data = st->Ist.Store.data; 4452024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* addr = st->Ist.Store.addr; 4453e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRType d_ty = typeOfIRExpr(pce->sb->tyenv, data); 4454024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* addrv = schemeEw_Atom( pce, addr ); 44551c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj IRTemp resSC = st->Ist.Store.resSC; 44561c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (resSC != IRTemp_INVALID) { 4457e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert(typeOfIRTemp(pce->sb->tyenv, resSC) == Ity_I1); 44581c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* viz, not something we want to shadow */ 44591c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* also, throw out all store-conditional cases that 44601c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj we can't handle */ 44611c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (pce->gWordTy == Ity_I32 && d_ty != Ity_I32) 44621c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto unhandled; 44631c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (pce->gWordTy == Ity_I64 && d_ty != Ity_I32 && d_ty != Ity_I64) 44641c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj goto unhandled; 44651c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 4466024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->gWordTy == Ity_I32) { 4467024598e40c84666cc311a42c256bbf880db3ac99sewardj /* ------ 32 bit host/guest (cough, cough) ------ */ 4468024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (d_ty) { 4469024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Integer word case */ 4470024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I32: { 4471024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* datav = schemeEw_Atom( pce, data ); 44721c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (resSC == IRTemp_INVALID) { 44731c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* "normal" store */ 44741c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj gen_dirty_v_WWWW( pce, 44751c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj &check_store4_P, "check_store4_P", 44761c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj addr, addrv, data, datav ); 44771c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } else { 44781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* store-conditional; need to snarf the success bit */ 44791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj IRTemp resSC32 44801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj = gen_dirty_W_WWWW( pce, 44811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj &check_store4C_P, 44821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "check_store4C_P", 44831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj addr, addrv, data, datav ); 44841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* presumably resSC32 will really be Ity_I32. In 44851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj any case we'll get jumped by the IR sanity 44861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj checker if it's not, when it sees the 44871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj following statement. */ 44881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj assign( 'I', pce, resSC, unop(Iop_32to1, mkexpr(resSC32)) ); 44891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 4490024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4491024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4492024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Integer subword cases */ 4493024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I16: 4494024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4495024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store2, "check_store2", 4496024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, 4497024598e40c84666cc311a42c256bbf880db3ac99sewardj uwiden_to_host_word( pce, data )); 4498024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4499024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I8: 4500024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4501024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store1, "check_store1", 4502024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, 4503024598e40c84666cc311a42c256bbf880db3ac99sewardj uwiden_to_host_word( pce, data )); 4504024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4505024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 64-bit float. Pass store data in 2 32-bit pieces. */ 4506024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F64: { 4507024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* d64 = assignNew( 'I', pce, Ity_I64, 4508024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_ReinterpF64asI64, data) ); 4509024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32, 4510024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64to32, d64) ); 4511024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32, 4512024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64HIto32, d64) ); 4513024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWWW( pce, 4514024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store8_ms4B_ls4B, 4515024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store8_ms4B_ls4B", 4516024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, dHi32, dLo32 ); 4517024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4518024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4519024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 32-bit float. We can just use _store4, but need 4520024598e40c84666cc311a42c256bbf880db3ac99sewardj to futz with the argument type. */ 4521024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F32: { 4522024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* i32 = assignNew( 'I', pce, Ity_I32, 4523024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_ReinterpF32asI32, 4524024598e40c84666cc311a42c256bbf880db3ac99sewardj data ) ); 4525024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4526024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store4, 4527024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store4", 4528024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, i32 ); 4529024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4530024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4531024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 64-bit int. Pass store data in 2 32-bit pieces. */ 4532024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I64: { 4533024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32, 4534024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64to32, data) ); 4535024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32, 4536024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64HIto32, data) ); 4537024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWWW( pce, 4538024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store8_ms4B_ls4B, 4539024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store8_ms4B_ls4B", 4540024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, dHi32, dLo32 ); 4541024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4542024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4543024598e40c84666cc311a42c256bbf880db3ac99sewardj 4544024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 128-bit vector. Pass store data in 4 32-bit pieces. 4545024598e40c84666cc311a42c256bbf880db3ac99sewardj This is all very ugly and inefficient, but it is 4546024598e40c84666cc311a42c256bbf880db3ac99sewardj hard to better without considerably complicating the 4547024598e40c84666cc311a42c256bbf880db3ac99sewardj store-handling schemes. */ 4548024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_V128: { 4549024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64, 4550024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_V128HIto64, data) ); 4551024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64, 4552024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_V128to64, data) ); 4553024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* w3 = assignNew( 'I', pce, Ity_I32, 4554024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64HIto32, dHi64) ); 4555024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* w2 = assignNew( 'I', pce, Ity_I32, 4556024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64to32, dHi64) ); 4557024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* w1 = assignNew( 'I', pce, Ity_I32, 4558024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64HIto32, dLo64) ); 4559024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* w0 = assignNew( 'I', pce, Ity_I32, 4560024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_64to32, dLo64) ); 4561024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_6W( pce, 4562024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store16_ms4B_4B_4B_ls4B, 4563024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store16_ms4B_4B_4B_ls4B", 4564024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, w3, w2, w1, w0 ); 4565024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4566024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4567024598e40c84666cc311a42c256bbf880db3ac99sewardj 4568024598e40c84666cc311a42c256bbf880db3ac99sewardj 4569024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 4570024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRType(d_ty); tl_assert(0); 4571024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4572024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4573024598e40c84666cc311a42c256bbf880db3ac99sewardj /* ------ 64 bit host/guest (cough, cough) ------ */ 4574024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (d_ty) { 4575024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Integer word case */ 4576024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I64: { 4577024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* datav = schemeEw_Atom( pce, data ); 45781c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (resSC == IRTemp_INVALID) { 45791c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* "normal" store */ 45801c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj gen_dirty_v_WWWW( pce, 45811c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj &check_store8_P, "check_store8_P", 45821c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj addr, addrv, data, datav ); 45831c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } else { 45841c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj IRTemp resSC64 45851c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj = gen_dirty_W_WWWW( pce, 45861c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj &check_store8C_P, 45871c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "check_store8C_P", 45881c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj addr, addrv, data, datav ); 45891c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj assign( 'I', pce, resSC, unop(Iop_64to1, mkexpr(resSC64)) ); 45901c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 4591024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4592024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4593024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Integer subword cases */ 4594024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I32: 45951c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj if (resSC == IRTemp_INVALID) { 45961c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* "normal" store */ 45971c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj gen_dirty_v_WWW( pce, 45981c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj &check_store4, "check_store4", 45991c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj addr, addrv, 46001c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj uwiden_to_host_word( pce, data )); 46011c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } else { 46021c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj /* store-conditional; need to snarf the success bit */ 46031c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj IRTemp resSC64 46041c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj = gen_dirty_W_WWW( pce, 46051c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj &check_store4C, 46061c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj "check_store4C", 46071c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj addr, addrv, 46081c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj uwiden_to_host_word( pce, data )); 46091c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj assign( 'I', pce, resSC, unop(Iop_64to1, mkexpr(resSC64)) ); 46101c0ce7a9edf8772773f6216dbad4bb04317d23b6sewardj } 4611024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4612024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I16: 4613024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4614024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store2, "check_store2", 4615024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, 4616024598e40c84666cc311a42c256bbf880db3ac99sewardj uwiden_to_host_word( pce, data )); 4617024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4618024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I8: 4619024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4620024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store1, "check_store1", 4621024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, 4622024598e40c84666cc311a42c256bbf880db3ac99sewardj uwiden_to_host_word( pce, data )); 4623024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4624024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 128-bit vector. Pass store data in 2 64-bit pieces. */ 4625024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_V128: { 4626024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64, 4627024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_V128HIto64, data) ); 4628024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64, 4629024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_V128to64, data) ); 4630024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWWW( pce, 4631024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store16_ms8B_ls8B, 4632024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store16_ms8B_ls8B", 4633024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, dHi64, dLo64 ); 4634024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4635024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4636024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 64-bit float. */ 4637024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F64: { 4638024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* dI = assignNew( 'I', pce, Ity_I64, 4639024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_ReinterpF64asI64, 4640024598e40c84666cc311a42c256bbf880db3ac99sewardj data ) ); 4641024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4642024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store8_all8B, 4643024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store8_all8B", 4644024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, dI ); 4645024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4646024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4647024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 32-bit float. We can just use _store4, but need 4648024598e40c84666cc311a42c256bbf880db3ac99sewardj to futz with the argument type. */ 4649024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F32: { 4650024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* i32 = assignNew( 'I', pce, Ity_I32, 4651024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_ReinterpF32asI32, 4652024598e40c84666cc311a42c256bbf880db3ac99sewardj data ) ); 4653024598e40c84666cc311a42c256bbf880db3ac99sewardj IRAtom* i64 = assignNew( 'I', pce, Ity_I64, 4654024598e40c84666cc311a42c256bbf880db3ac99sewardj unop(Iop_32Uto64, 4655024598e40c84666cc311a42c256bbf880db3ac99sewardj i32 ) ); 4656024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WWW( pce, 4657024598e40c84666cc311a42c256bbf880db3ac99sewardj &check_store4, 4658024598e40c84666cc311a42c256bbf880db3ac99sewardj "check_store4", 4659024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv, i64 ); 4660024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4661024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4662024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 4663024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRType(d_ty); tl_assert(0); 4664024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4665024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4666024598e40c84666cc311a42c256bbf880db3ac99sewardj /* And don't copy the original, since the helper does the 4667024598e40c84666cc311a42c256bbf880db3ac99sewardj store. Ick. */ 4668024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4669024598e40c84666cc311a42c256bbf880db3ac99sewardj } /* case Ist_Store */ 4670024598e40c84666cc311a42c256bbf880db3ac99sewardj 4671024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ist_WrTmp: { 4672024598e40c84666cc311a42c256bbf880db3ac99sewardj /* This is the only place we have to deal with the full 4673024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr range. In all other places where an IRExpr could 4674024598e40c84666cc311a42c256bbf880db3ac99sewardj appear, we in fact only get an atom (Iex_RdTmp or 4675024598e40c84666cc311a42c256bbf880db3ac99sewardj Iex_Const). */ 4676024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* e = st->Ist.WrTmp.data; 4677e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj IRType e_ty = typeOfIRExpr( pce->sb->tyenv, e ); 4678024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool isWord = e_ty == pce->gWordTy; 4679024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp dst = st->Ist.WrTmp.tmp; 4680024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp dstv = isWord ? newShadowTmp( pce, dst ) 4681024598e40c84666cc311a42c256bbf880db3ac99sewardj : IRTemp_INVALID; 4682024598e40c84666cc311a42c256bbf880db3ac99sewardj 4683024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (e->tag) { 4684024598e40c84666cc311a42c256bbf880db3ac99sewardj 4685024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Const: { 4686024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4687024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4688024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) ); 4689024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4690024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4691024598e40c84666cc311a42c256bbf880db3ac99sewardj 4692024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_CCall: { 4693024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4694024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4695024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4696024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr( gen_call_nonptr_or_unknown_w( 4697024598e40c84666cc311a42c256bbf880db3ac99sewardj pce, mkexpr(dst)))); 4698024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4699024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4700024598e40c84666cc311a42c256bbf880db3ac99sewardj 4701024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Mux0X: { 4702024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Just steer the shadow values in the same way as the 4703024598e40c84666cc311a42c256bbf880db3ac99sewardj originals. */ 4704024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4705024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4706024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4707024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr_Mux0X( 4708024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Mux0X.cond, 4709024598e40c84666cc311a42c256bbf880db3ac99sewardj schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ), 4710024598e40c84666cc311a42c256bbf880db3ac99sewardj schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) )); 4711024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4712024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4713024598e40c84666cc311a42c256bbf880db3ac99sewardj 4714024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_RdTmp: { 4715024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4716024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4717024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, schemeEw_Atom( pce, e )); 4718024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4719024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4720024598e40c84666cc311a42c256bbf880db3ac99sewardj 4721024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Load: { 4722024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* addr = e->Iex.Load.addr; 4723024598e40c84666cc311a42c256bbf880db3ac99sewardj HChar* h_nm = NULL; 4724024598e40c84666cc311a42c256bbf880db3ac99sewardj void* h_fn = NULL; 4725024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr* addrv = NULL; 4726024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->gWordTy == Ity_I32) { 4727024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 32 bit host/guest (cough, cough) */ 4728024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (e_ty) { 4729024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Ity_I32: helper returns shadow value. */ 4730024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I32: h_fn = &check_load4_P; 4731024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load4_P"; break; 4732024598e40c84666cc311a42c256bbf880db3ac99sewardj /* all others: helper does not return a shadow 4733024598e40c84666cc311a42c256bbf880db3ac99sewardj value. */ 4734024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_V128: h_fn = &check_load16; 4735024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load16"; break; 4736024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I64: 4737024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F64: h_fn = &check_load8; 4738024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load8"; break; 4739024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F32: h_fn = &check_load4; 4740024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load4"; break; 4741024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I16: h_fn = &check_load2; 4742024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load2"; break; 4743024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I8: h_fn = &check_load1; 4744024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load1"; break; 4745024598e40c84666cc311a42c256bbf880db3ac99sewardj default: ppIRType(e_ty); tl_assert(0); 4746024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4747024598e40c84666cc311a42c256bbf880db3ac99sewardj addrv = schemeEw_Atom( pce, addr ); 4748024598e40c84666cc311a42c256bbf880db3ac99sewardj if (e_ty == Ity_I32) { 4749024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4750024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm, 4751024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv )) ); 4752024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4753024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv ); 4754024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4755024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4756024598e40c84666cc311a42c256bbf880db3ac99sewardj /* 64 bit host/guest (cough, cough) */ 4757024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (e_ty) { 4758024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Ity_I64: helper returns shadow value. */ 4759024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I64: h_fn = &check_load8_P; 4760024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load8_P"; break; 4761024598e40c84666cc311a42c256bbf880db3ac99sewardj /* all others: helper does not return a shadow 4762024598e40c84666cc311a42c256bbf880db3ac99sewardj value. */ 4763024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_V128: h_fn = &check_load16; 4764024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load16"; break; 4765024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F64: h_fn = &check_load8; 4766024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load8"; break; 4767024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_F32: 4768024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I32: h_fn = &check_load4; 4769024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load4"; break; 4770024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I16: h_fn = &check_load2; 4771024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load2"; break; 4772024598e40c84666cc311a42c256bbf880db3ac99sewardj case Ity_I8: h_fn = &check_load1; 4773024598e40c84666cc311a42c256bbf880db3ac99sewardj h_nm = "check_load1"; break; 4774024598e40c84666cc311a42c256bbf880db3ac99sewardj default: ppIRType(e_ty); tl_assert(0); 4775024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4776024598e40c84666cc311a42c256bbf880db3ac99sewardj addrv = schemeEw_Atom( pce, addr ); 4777024598e40c84666cc311a42c256bbf880db3ac99sewardj if (e_ty == Ity_I64) { 4778024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4779024598e40c84666cc311a42c256bbf880db3ac99sewardj mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm, 4780024598e40c84666cc311a42c256bbf880db3ac99sewardj addr, addrv )) ); 4781024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4782024598e40c84666cc311a42c256bbf880db3ac99sewardj gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv ); 4783024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4784024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4785024598e40c84666cc311a42c256bbf880db3ac99sewardj /* copy the original -- must happen after the helper call */ 4786024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4787024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4788024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4789024598e40c84666cc311a42c256bbf880db3ac99sewardj 4790024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_GetI: { 4791024598e40c84666cc311a42c256bbf880db3ac99sewardj IRRegArray* descr = e->Iex.GetI.descr; 4792024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4793024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(descr && descr->elemTy); 4794024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_integer_guest_reg_array(descr)) { 4795024598e40c84666cc311a42c256bbf880db3ac99sewardj /* if this fails, is_integer_guest_reg_array is 4796024598e40c84666cc311a42c256bbf880db3ac99sewardj returning bogus results */ 4797024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isWord); 4798024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 4799024598e40c84666cc311a42c256bbf880db3ac99sewardj 'I', pce, dstv, 4800024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr_GetI( 4801024598e40c84666cc311a42c256bbf880db3ac99sewardj mkIRRegArray(descr->base + pce->guest_state_sizeB, 4802024598e40c84666cc311a42c256bbf880db3ac99sewardj descr->elemTy, descr->nElems), 4803024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.GetI.ix, 4804024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.GetI.bias 4805024598e40c84666cc311a42c256bbf880db3ac99sewardj ) 4806024598e40c84666cc311a42c256bbf880db3ac99sewardj ); 4807024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4808024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4809024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4810024598e40c84666cc311a42c256bbf880db3ac99sewardj 4811024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Get: { 4812024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4813024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) { 4814024598e40c84666cc311a42c256bbf880db3ac99sewardj /* guest-word-typed tmp assignment, so it will have a 4815024598e40c84666cc311a42c256bbf880db3ac99sewardj shadow tmp, and we must make an assignment to 4816024598e40c84666cc311a42c256bbf880db3ac99sewardj that */ 4817024598e40c84666cc311a42c256bbf880db3ac99sewardj if (is_integer_guest_reg(e->Iex.Get.offset, 4818024598e40c84666cc311a42c256bbf880db3ac99sewardj sizeofIRType(e->Iex.Get.ty))) { 4819024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, 4820024598e40c84666cc311a42c256bbf880db3ac99sewardj IRExpr_Get( e->Iex.Get.offset 4821024598e40c84666cc311a42c256bbf880db3ac99sewardj + pce->guest_state_sizeB, 4822024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Get.ty) ); 4823024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4824024598e40c84666cc311a42c256bbf880db3ac99sewardj if (pce->hWordTy == Ity_I32) { 4825024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkU32( (UWord)NONPTR )); 4826024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4827024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'I', pce, dstv, mkU64( (UWord)NONPTR )); 4828024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4829024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4830024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 4831024598e40c84666cc311a42c256bbf880db3ac99sewardj /* tmp isn't guest-word-typed, so isn't shadowed, so 4832024598e40c84666cc311a42c256bbf880db3ac99sewardj generate no instrumentation */ 4833024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4834024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4835024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4836024598e40c84666cc311a42c256bbf880db3ac99sewardj 4837024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Unop: { 4838024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4839024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Unop.arg)); 4840024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4841024598e40c84666cc311a42c256bbf880db3ac99sewardj instrument_arithop( pce, dst, dstv, e->Iex.Unop.op, 4842024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Unop.arg, 4843024598e40c84666cc311a42c256bbf880db3ac99sewardj NULL, NULL, NULL ); 4844024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4845024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4846024598e40c84666cc311a42c256bbf880db3ac99sewardj 4847024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Binop: { 4848024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4849024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Binop.arg1)); 4850024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Binop.arg2)); 4851024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4852024598e40c84666cc311a42c256bbf880db3ac99sewardj instrument_arithop( pce, dst, dstv, e->Iex.Binop.op, 4853024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Binop.arg1, e->Iex.Binop.arg2, 4854024598e40c84666cc311a42c256bbf880db3ac99sewardj NULL, NULL ); 4855024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4856024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4857024598e40c84666cc311a42c256bbf880db3ac99sewardj 4858024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Triop: { 4859024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4860024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Triop.arg1)); 4861024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Triop.arg2)); 4862024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Triop.arg3)); 4863024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4864024598e40c84666cc311a42c256bbf880db3ac99sewardj instrument_arithop( pce, dst, dstv, e->Iex.Triop.op, 4865024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Triop.arg1, e->Iex.Triop.arg2, 4866024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Triop.arg3, NULL ); 4867024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4868024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4869024598e40c84666cc311a42c256bbf880db3ac99sewardj 4870024598e40c84666cc311a42c256bbf880db3ac99sewardj case Iex_Qop: { 4871024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', pce, st ); 4872024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Qop.arg1)); 4873024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Qop.arg2)); 4874024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Qop.arg3)); 4875024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isIRAtom(e->Iex.Qop.arg4)); 4876024598e40c84666cc311a42c256bbf880db3ac99sewardj if (isWord) 4877024598e40c84666cc311a42c256bbf880db3ac99sewardj instrument_arithop( pce, dst, dstv, e->Iex.Qop.op, 4878024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Qop.arg1, e->Iex.Qop.arg2, 4879024598e40c84666cc311a42c256bbf880db3ac99sewardj e->Iex.Qop.arg3, e->Iex.Qop.arg4 ); 4880024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4881024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4882024598e40c84666cc311a42c256bbf880db3ac99sewardj 4883024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 4884024598e40c84666cc311a42c256bbf880db3ac99sewardj goto unhandled; 4885024598e40c84666cc311a42c256bbf880db3ac99sewardj } /* switch (e->tag) */ 4886024598e40c84666cc311a42c256bbf880db3ac99sewardj 4887024598e40c84666cc311a42c256bbf880db3ac99sewardj break; 4888024598e40c84666cc311a42c256bbf880db3ac99sewardj 4889024598e40c84666cc311a42c256bbf880db3ac99sewardj } /* case Ist_WrTmp */ 4890024598e40c84666cc311a42c256bbf880db3ac99sewardj 4891024598e40c84666cc311a42c256bbf880db3ac99sewardj default: 4892024598e40c84666cc311a42c256bbf880db3ac99sewardj unhandled: 4893024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRStmt(st); 4894024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(0); 4895024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4896024598e40c84666cc311a42c256bbf880db3ac99sewardj} 4897024598e40c84666cc311a42c256bbf880db3ac99sewardj 4898024598e40c84666cc311a42c256bbf880db3ac99sewardj 4899e6451332ee19f6d70821bf8e24781ff8868bdb3csewardjstatic IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque ) 4900e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj{ 4901e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj PCEnv* pce = (PCEnv*)opaque; 4902e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj return newTemp( pce, ty, NonShad ); 4903e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj} 4904e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 4905e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 4906024598e40c84666cc311a42c256bbf880db3ac99sewardjIRSB* h_instrument ( VgCallbackClosure* closure, 4907024598e40c84666cc311a42c256bbf880db3ac99sewardj IRSB* sbIn, 4908024598e40c84666cc311a42c256bbf880db3ac99sewardj VexGuestLayout* layout, 4909024598e40c84666cc311a42c256bbf880db3ac99sewardj VexGuestExtents* vge, 4910024598e40c84666cc311a42c256bbf880db3ac99sewardj IRType gWordTy, IRType hWordTy ) 4911024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 4912024598e40c84666cc311a42c256bbf880db3ac99sewardj Bool verboze = 0||False; 4913024598e40c84666cc311a42c256bbf880db3ac99sewardj Int i /*, j*/; 4914024598e40c84666cc311a42c256bbf880db3ac99sewardj PCEnv pce; 4915024598e40c84666cc311a42c256bbf880db3ac99sewardj struct _SGEnv* sgenv; 4916024598e40c84666cc311a42c256bbf880db3ac99sewardj 4917024598e40c84666cc311a42c256bbf880db3ac99sewardj if (gWordTy != hWordTy) { 4918024598e40c84666cc311a42c256bbf880db3ac99sewardj /* We don't currently support this case. */ 4919024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(tool_panic)("host/guest word size mismatch"); 4920024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4921024598e40c84666cc311a42c256bbf880db3ac99sewardj 4922024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Check we're not completely nuts */ 4923024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UWord) == sizeof(void*)); 4924024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(Word) == sizeof(void*)); 4925024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(Addr) == sizeof(void*)); 4926024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(ULong) == 8); 4927024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(Long) == 8); 4928024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(Addr64) == 8); 4929024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(UInt) == 4); 4930024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sizeof(Int) == 4); 4931024598e40c84666cc311a42c256bbf880db3ac99sewardj 4932e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* Set up the running environment. Both .sb and .tmpMap are 4933e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj modified as we go along. Note that tmps are added to both 4934e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj .sb->tyenv and .tmpMap together, so the valid index-set for 4935e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj those two arrays should always be identical. */ 4936e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj VG_(memset)(&pce, 0, sizeof(pce)); 4937e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj pce.sb = deepCopyIRSBExceptStmts(sbIn); 4938024598e40c84666cc311a42c256bbf880db3ac99sewardj pce.trace = verboze; 4939024598e40c84666cc311a42c256bbf880db3ac99sewardj pce.hWordTy = hWordTy; 4940024598e40c84666cc311a42c256bbf880db3ac99sewardj pce.gWordTy = gWordTy; 4941024598e40c84666cc311a42c256bbf880db3ac99sewardj pce.guest_state_sizeB = layout->total_sizeB; 4942024598e40c84666cc311a42c256bbf880db3ac99sewardj 4943e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj pce.qmpMap = VG_(newXA)( VG_(malloc), "pc.h_instrument.1", VG_(free), 4944e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj sizeof(TempMapEnt)); 4945e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj for (i = 0; i < sbIn->tyenv->types_used; i++) { 4946e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj TempMapEnt ent; 4947e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent.kind = NonShad; 4948e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj ent.shadow = IRTemp_INVALID; 4949e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj VG_(addToXA)( pce.qmpMap, &ent ); 4950e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj } 4951e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert( VG_(sizeXA)( pce.qmpMap ) == sbIn->tyenv->types_used ); 4952e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 4953e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* Also set up for the sg_ instrumenter. See comments at the top 4954e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj of this instrumentation section for details. The two parameters 4955e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj constitute a closure, which sg_ can use to correctly generate 4956e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj new IRTemps as needed. */ 4957e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj sgenv = sg_instrument_init( for_sg__newIRTemp_cb, 4958e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj (void*)&pce ); 4959024598e40c84666cc311a42c256bbf880db3ac99sewardj 4960024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Stay sane. These two should agree! */ 4961024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE); 4962024598e40c84666cc311a42c256bbf880db3ac99sewardj 4963024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Copy verbatim any IR preamble preceding the first IMark */ 4964024598e40c84666cc311a42c256bbf880db3ac99sewardj 4965024598e40c84666cc311a42c256bbf880db3ac99sewardj i = 0; 4966024598e40c84666cc311a42c256bbf880db3ac99sewardj while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) { 4967024598e40c84666cc311a42c256bbf880db3ac99sewardj IRStmt* st = sbIn->stmts[i]; 4968024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(st); 4969024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(isFlatIRStmt(st)); 4970024598e40c84666cc311a42c256bbf880db3ac99sewardj stmt( 'C', &pce, sbIn->stmts[i] ); 4971024598e40c84666cc311a42c256bbf880db3ac99sewardj i++; 4972024598e40c84666cc311a42c256bbf880db3ac99sewardj } 4973024598e40c84666cc311a42c256bbf880db3ac99sewardj 4974024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Nasty problem. IR optimisation of the pre-instrumented IR may 4975024598e40c84666cc311a42c256bbf880db3ac99sewardj cause the IR following the preamble to contain references to IR 4976024598e40c84666cc311a42c256bbf880db3ac99sewardj temporaries defined in the preamble. Because the preamble isn't 4977024598e40c84666cc311a42c256bbf880db3ac99sewardj instrumented, these temporaries don't have any shadows. 4978024598e40c84666cc311a42c256bbf880db3ac99sewardj Nevertheless uses of them following the preamble will cause 4979024598e40c84666cc311a42c256bbf880db3ac99sewardj memcheck to generate references to their shadows. End effect is 4980024598e40c84666cc311a42c256bbf880db3ac99sewardj to cause IR sanity check failures, due to references to 4981024598e40c84666cc311a42c256bbf880db3ac99sewardj non-existent shadows. This is only evident for the complex 4982024598e40c84666cc311a42c256bbf880db3ac99sewardj preambles used for function wrapping on TOC-afflicted platforms 4983024598e40c84666cc311a42c256bbf880db3ac99sewardj (ppc64-linux, ppc32-aix5, ppc64-aix5). 4984024598e40c84666cc311a42c256bbf880db3ac99sewardj 4985024598e40c84666cc311a42c256bbf880db3ac99sewardj The following loop therefore scans the preamble looking for 4986024598e40c84666cc311a42c256bbf880db3ac99sewardj assignments to temporaries. For each one found it creates an 4987024598e40c84666cc311a42c256bbf880db3ac99sewardj assignment to the corresponding shadow temp, marking it as 4988024598e40c84666cc311a42c256bbf880db3ac99sewardj 'defined'. This is the same resulting IR as if the main 4989024598e40c84666cc311a42c256bbf880db3ac99sewardj instrumentation loop before had been applied to the statement 4990024598e40c84666cc311a42c256bbf880db3ac99sewardj 'tmp = CONSTANT'. 4991024598e40c84666cc311a42c256bbf880db3ac99sewardj */ 4992024598e40c84666cc311a42c256bbf880db3ac99sewardj#if 0 4993024598e40c84666cc311a42c256bbf880db3ac99sewardj // FIXME: this isn't exactly right; only needs to generate shadows 4994024598e40c84666cc311a42c256bbf880db3ac99sewardj // for guest-word-typed temps 4995024598e40c84666cc311a42c256bbf880db3ac99sewardj for (j = 0; j < i; j++) { 4996024598e40c84666cc311a42c256bbf880db3ac99sewardj if (sbIn->stmts[j]->tag == Ist_WrTmp) { 4997024598e40c84666cc311a42c256bbf880db3ac99sewardj /* findShadowTmpV checks its arg is an original tmp; 4998024598e40c84666cc311a42c256bbf880db3ac99sewardj no need to assert that here. */ 4999024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp; 5000024598e40c84666cc311a42c256bbf880db3ac99sewardj IRTemp tmp_s = findShadowTmp(&pce, tmp_o); 5001024598e40c84666cc311a42c256bbf880db3ac99sewardj IRType ty_s = typeOfIRTemp(sbIn->tyenv, tmp_s); 5002024598e40c84666cc311a42c256bbf880db3ac99sewardj assign( 'V', &pce, tmp_s, definedOfType( ty_s ) ); 5003024598e40c84666cc311a42c256bbf880db3ac99sewardj if (0) { 5004024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j); 5005024598e40c84666cc311a42c256bbf880db3ac99sewardj ppIRType( ty_s ); 5006024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(printf)("\n"); 5007024598e40c84666cc311a42c256bbf880db3ac99sewardj } 5008024598e40c84666cc311a42c256bbf880db3ac99sewardj } 5009024598e40c84666cc311a42c256bbf880db3ac99sewardj } 5010024598e40c84666cc311a42c256bbf880db3ac99sewardj#endif 5011024598e40c84666cc311a42c256bbf880db3ac99sewardj 5012024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Iterate over the remaining stmts to generate instrumentation. */ 5013024598e40c84666cc311a42c256bbf880db3ac99sewardj 5014024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sbIn->stmts_used > 0); 5015024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(i >= 0); 5016024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(i < sbIn->stmts_used); 5017024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert(sbIn->stmts[i]->tag == Ist_IMark); 5018024598e40c84666cc311a42c256bbf880db3ac99sewardj 5019024598e40c84666cc311a42c256bbf880db3ac99sewardj for (/*use current i*/; i < sbIn->stmts_used; i++) { 5020024598e40c84666cc311a42c256bbf880db3ac99sewardj /* generate sg_ instrumentation for this stmt */ 5021e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj sg_instrument_IRStmt( sgenv, pce.sb, sbIn->stmts[i], 5022024598e40c84666cc311a42c256bbf880db3ac99sewardj layout, gWordTy, hWordTy ); 5023024598e40c84666cc311a42c256bbf880db3ac99sewardj /* generate h_ instrumentation for this stmt */ 5024024598e40c84666cc311a42c256bbf880db3ac99sewardj schemeS( &pce, sbIn->stmts[i] ); 5025024598e40c84666cc311a42c256bbf880db3ac99sewardj } 5026024598e40c84666cc311a42c256bbf880db3ac99sewardj 5027024598e40c84666cc311a42c256bbf880db3ac99sewardj /* generate sg_ instrumentation for the final jump */ 5028e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj sg_instrument_final_jump( sgenv, pce.sb, sbIn->next, sbIn->jumpkind, 5029024598e40c84666cc311a42c256bbf880db3ac99sewardj layout, gWordTy, hWordTy ); 5030024598e40c84666cc311a42c256bbf880db3ac99sewardj 5031024598e40c84666cc311a42c256bbf880db3ac99sewardj /* and finalise .. */ 5032024598e40c84666cc311a42c256bbf880db3ac99sewardj sg_instrument_fini( sgenv ); 5033024598e40c84666cc311a42c256bbf880db3ac99sewardj 5034e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj /* If this fails, there's been some serious snafu with tmp management, 5035e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj that should be investigated. */ 5036e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj tl_assert( VG_(sizeXA)( pce.qmpMap ) == pce.sb->tyenv->types_used ); 5037e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj VG_(deleteXA)( pce.qmpMap ); 5038e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj 5039e6451332ee19f6d70821bf8e24781ff8868bdb3csewardj return pce.sb; 5040024598e40c84666cc311a42c256bbf880db3ac99sewardj} 5041024598e40c84666cc311a42c256bbf880db3ac99sewardj 5042024598e40c84666cc311a42c256bbf880db3ac99sewardj 5043024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 5044024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Initialisation ---*/ 5045024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 5046024598e40c84666cc311a42c256bbf880db3ac99sewardj 5047024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_pre_clo_init ( void ) 5048024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 5049024598e40c84666cc311a42c256bbf880db3ac99sewardj // Other initialisation 5050024598e40c84666cc311a42c256bbf880db3ac99sewardj init_shadow_memory(); 5051024598e40c84666cc311a42c256bbf880db3ac99sewardj init_lossage(); 5052024598e40c84666cc311a42c256bbf880db3ac99sewardj} 5053024598e40c84666cc311a42c256bbf880db3ac99sewardj 5054024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_post_clo_init ( void ) 5055024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 5056024598e40c84666cc311a42c256bbf880db3ac99sewardj} 5057024598e40c84666cc311a42c256bbf880db3ac99sewardj 5058024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 5059024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Finalisation ---*/ 5060024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 5061024598e40c84666cc311a42c256bbf880db3ac99sewardj 5062024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid h_fini ( Int exitcode ) 5063024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 5064024598e40c84666cc311a42c256bbf880db3ac99sewardj if (VG_(clo_verbosity) >= 2) { 5065024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_DebugMsg, 5066024598e40c84666cc311a42c256bbf880db3ac99sewardj " h_: %'10llu client allocs, %'10llu client frees", 5067024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__client_mallocs, stats__client_frees); 5068024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_DebugMsg, 5069024598e40c84666cc311a42c256bbf880db3ac99sewardj " h_: %'10llu Segs allocd, %'10llu Segs recycled", 5070024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__segs_allocd, stats__segs_recycled); 5071024598e40c84666cc311a42c256bbf880db3ac99sewardj } 5072024598e40c84666cc311a42c256bbf880db3ac99sewardj 50734815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#if 0 5074024598e40c84666cc311a42c256bbf880db3ac99sewardj if (h_clo_lossage_check) { 5075024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_UserMsg, ""); 5076024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_UserMsg, "%12lld total memory references", 5077024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__tot_mem_refs); 5078024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_UserMsg, "%12lld of which are in a known segment", 5079024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__refs_in_a_seg); 5080024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_UserMsg, "%12lld of which are 'lost' w.r.t the seg", 5081024598e40c84666cc311a42c256bbf880db3ac99sewardj stats__refs_lost_seg); 5082024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_UserMsg, ""); 5083024598e40c84666cc311a42c256bbf880db3ac99sewardj show_lossage(); 5084024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_(message)(Vg_UserMsg, ""); 5085024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 5086024598e40c84666cc311a42c256bbf880db3ac99sewardj tl_assert( 0 == VG_(OSetGen_Size)(lossage) ); 5087024598e40c84666cc311a42c256bbf880db3ac99sewardj } 50884815eb5cc0e96a3b76aae246e3ca7a8b3394c46csewardj#endif 5089024598e40c84666cc311a42c256bbf880db3ac99sewardj} 5090024598e40c84666cc311a42c256bbf880db3ac99sewardj 5091024598e40c84666cc311a42c256bbf880db3ac99sewardj 5092024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 5093024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- end h_main.c ---*/ 5094024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/ 5095