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