2 /*--------------------------------------------------------------------*/
3 /*--- Ptrcheck: a pointer-use checker. ---*/
4 /*--- This file checks heap accesses. ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Ptrcheck, a Valgrind tool for checking pointer
12 Initial version (Annelid):
14 Copyright (C) 2003-2010 Nicholas Nethercote
19 Copyright (C) 2008-2010 OpenWorks Ltd
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 This program is distributed in the hope that it will be useful, but
28 WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
37 The GNU General Public License is contained in the file COPYING.
40 // FIXME: 64-bit cleanness, check the following
41 // struct _ISNode.ownerCount is 32-bit
42 // struct _ISNode.topLevel is 32-bit
43 // or is that not really right now? add assertion checks about
44 // the max size of a node
46 // FIXME: should we shadow %RIP? Maybe not.
48 // FIXME: shadows of temporaries created in preamble, a la memcheck?
50 // FIXME: result of add_new_segment is always ignored
52 // FIXME: the mechanism involving last_seg_added is really ugly.
53 // Do something cleaner.
55 // FIXME: post_reg_write_clientcall: check function pointer comparisons
56 // are safe on toc-afflicted platforms
58 // FIXME: tidy up findShadowTmp
60 // FIXME: post_reg_write_demux(Vg_CoreSysCall) is redundant w.r.t.
61 // the default 'NONPTR' behaviour of post_syscall. post_reg_write_demux
62 // is called first, then post_syscall.
64 // FIXME: check nothing is mapped in the lowest 1M of memory at
65 // startup, or quit (to do with nonptr_or_unknown, also sync 1M
66 // magic value with PIE default load address in m_ume.c.
68 // FIXME: consider whether we could paint memory acquired from
69 // sys_read etc as NONPTR rather than UNKNOWN.
71 // XXX: recycle freed segments
73 //--------------------------------------------------------------
75 // HeapBlock.id :: Seg (stored as heap shadowchunk; always non-zero)
76 // MemLoc.aseg :: Seg (implicitly stored)
77 // MemLoc.vseg :: Seg (explicitly stored as the shadow memory)
78 // RegLoc.vseg :: Seg (explicitly stored as shadow registers)
80 // A Seg is made when new memory is created, eg. with malloc() or mmap().
81 // There are two other Segs:
82 // - NONPTR: for something that's definitely not a pointer
83 // - UNKNOWN: for something that could be a pointer
84 // - BOTTOM: used with pointer differences (see below)
86 // MemLoc.vseg is done at word granularity. If a pointer is written
87 // to memory misaligned, the information about it will be lost -- it's
88 // treated as two sub-word writes to two adjacent words. This avoids
89 // certain nasty cases that could arise if we tried to track unaligned
90 // pointers. Fortunately, misalignment is rare so we don't lose much
91 // information this way.
93 // MemLoc.aseg is done at byte granularity, and *implicitly* -- ie. not
94 // directly accessible like MemLoc.vseg, but only by searching through all
95 // the segments. Fortunately, it's mostly checked at LOADs/STOREs; at that
96 // point we have a pointer p to the MemLoc m as the other arg of the
97 // LOAD/STORE, so we can check to see if the p.vseg's range includes m. If
98 // not, it's an error and we have to search through all segments to find out
99 // what m.aseg really is. That's still pretty fast though, thanks to the
100 // interval skip-list used. With syscalls we must also do the skip-list
101 // search, but only on the first and last bytes touched.
102 //--------------------------------------------------------------
104 //--------------------------------------------------------------
106 // - see comment at top of SK_(instrument)() for how sub-word ops are
109 // - ioctl(), socketcall() (and ipc() will be) assumed to return non-pointers
111 // - FPU_W is assumed to never write pointers.
113 // - Assuming none of the post_mem_writes create segments worth tracking.
115 // - Treating mmap'd segments (all! including code) like heap segments. But
116 // their ranges can change, new ones can be created by unmapping parts of
117 // old segments, etc. But this nasty behaviour seems to never happen --
118 // there are assertions checking it.
119 //--------------------------------------------------------------
121 //--------------------------------------------------------------
122 // What I am checking:
124 // * ADD, OR, LEA2: error if two pointer inputs.
125 // * ADC, SBB: error if one or two pointer inputs.
126 // * AND, OR: error if two unequal pointer inputs.
127 // * NEG: error if pointer input.
128 // * {,i}mul_32_64 if either input is a pointer.
129 // * shldl/shrdl, bsf/bsr if any inputs are pointers.
132 // * ptr.vseg must match ptee.aseg.
133 // * ptee.aseg must not be a freed segment.
135 // - syscalls: for those accessing memory, look at first and last bytes:
136 // * check first.aseg == last.aseg
137 // * check first.aseg and last.aseg are not freed segments.
139 // What I am not checking, that I expected to when I started:
140 // - AND, XOR: allowing two pointers to be used if both from the same segment,
141 // because "xor %r,%r" is commonly used to zero %r, and "test %r,%r"
142 // (which is translated with an AND) is common too.
144 // - div_64_32/idiv_64_32 can take pointer inputs for the dividend;
145 // division doesn't make sense, but modulo does, and they're done with the
146 // same instruction. (Could try to be super-clever and watch the outputs
147 // to see if the quotient is used, but not worth it.)
149 // - mul_64_32/imul_64_32 can take pointers inputs for one arg or the
150 // other, but not both. This is because some programs (eg. Mozilla
151 // Firebird) multiply pointers in hash routines.
153 // - NEG: can take a pointer. It happens in glibc in a few places. I've
154 // seen the code, didn't understand it, but it's done deliberately.
156 // What I am not checking/doing, but could, but it would require more
157 // instrumentation and/or slow things down a bit:
158 // - SUB: when differencing two pointers, result is BOTTOM, ie. "don't
159 // check". Could link segments instead, slower but a bit more accurate.
160 // Also use BOTTOM when doing (ptr - unknown), which could be a pointer
161 // difference with a stack/static pointer.
163 // - PUTF: input should be non-pointer
165 // - arithmetic error messages: eg. for adding two pointers, just giving the
166 // segments, not the actual pointers.
168 // What I am not checking, and would be difficult:
169 // - mmap(...MAP_FIXED...) is not handled specially. It might be used in
170 // ways that fool Ptrcheck into giving false positives.
172 // - syscalls: for those accessing memory, not checking that the asegs of the
173 // accessed words match the vseg of the accessing pointer, because the
174 // vseg is not easily accessible at the required time (would required
175 // knowing for every syscall which register each arg came in, and looking
178 // What I am not checking, and would be difficult, but doesn't matter:
179 // - free(p): similar to syscalls, not checking that the p.vseg matches the
180 // aseg of the first byte in the block. However, Memcheck does an
181 // equivalent "bad free" check using shadow_chunks; indeed, Ptrcheck could
182 // do the same check, but there's no point duplicating functionality. So
186 // - not doing anything with mprotect(); probably not worth the effort.
187 //--------------------------------------------------------------
189 //--------------------------------------------------------------
191 // - Segments for stack frames. Would detect (some, large) stack
192 // over/under-runs, dangling pointers.
194 // - Segments for static data. Would detect over/under-runs. Requires
195 // reading debug info.
196 //--------------------------------------------------------------
198 //--------------------------------------------------------------
199 // Some profiling results:
200 // twolf konq date sz
201 // 1. started 35.0s 14.7
202 // 2. introduced GETV/PUTV 30.2s 10.1
203 // 3. inlined check_load_or_store 5.6s 27.5s 10.1
204 // 4. (made check_load, check_store4 regparm(0)) (27.9s) (11.0)
205 // 5. um, not sure 5.3s 27.3s 10.6
207 // 6. after big changes, corrections 11.2s 32.8s 14.0
208 // 7. removed link-segment chasing in check/L/S 8.9s 30.8s 14.0
209 // 8. avoiding do_lea1 if k is a nonptr 8.0s 28.0s 12.9
210 //--------------------------------------------------------------
212 //#include "vg_skin.h"
214 #include "pub_tool_basics.h"
215 #include "pub_tool_libcbase.h"
216 #include "pub_tool_libcprint.h"
217 #include "pub_tool_libcassert.h"
218 #include "pub_tool_mallocfree.h"
219 #include "pub_tool_execontext.h"
220 #include "pub_tool_hashtable.h"
221 #include "pub_tool_tooliface.h"
222 #include "pub_tool_replacemalloc.h"
223 #include "pub_tool_options.h"
224 #include "pub_tool_execontext.h"
225 #include "pub_tool_aspacemgr.h" // VG_(am_shadow_malloc)
226 #include "pub_tool_vki.h" // VKI_MAX_PAGE_SIZE
227 #include "pub_tool_machine.h" // VG_({get,set}_shadow_regs_area) et al
228 #include "pub_tool_debuginfo.h" // VG_(get_fnname)
229 #include "pub_tool_threadstate.h" // VG_(get_running_tid)
230 #include "pub_tool_oset.h"
231 #include "pub_tool_vkiscnums.h"
232 #include "pub_tool_machine.h"
233 #include "pub_tool_wordfm.h"
234 #include "pub_tool_xarray.h"
236 #include "pc_common.h"
238 //#include "h_list.h"
241 #include "sg_main.h" // sg_instrument_*, and struct _SGEnv
245 /*------------------------------------------------------------*/
246 /*--- Debug/trace options ---*/
247 /*------------------------------------------------------------*/
249 /* Set to 1 to do sanity checks on Seg values in many places, which
250 checks if bogus Segs are in circulation. Quite expensive from a
251 performance point of view. */
254 static ULong stats__client_mallocs = 0;
255 static ULong stats__client_frees = 0;
256 static ULong stats__segs_allocd = 0;
257 static ULong stats__segs_recycled = 0;
260 //////////////////////////////////////////////////////////////
262 // Segments low level storage //
264 //////////////////////////////////////////////////////////////
266 // NONPTR, UNKNOWN, BOTTOM defined in h_main.h since
267 // pc_common.c needs to see them, for error processing
269 // we only start recycling segs when this many exist
270 #define N_FREED_SEGS (1 * 1000 * 1000)
274 SizeT szB; /* may be zero */
275 ExeContext* ec; /* where malloc'd or freed */
276 /* When 1, indicates block is in use. Otherwise, used to form a
277 linked list of freed blocks, running from oldest freed block to
278 the most recently freed block. */
279 struct _Seg* nextfree;
282 // Determines if 'a' is before, within, or after seg's range. Sets 'cmp' to
283 // -1/0/1 accordingly. Sets 'n' to the number of bytes before/within/after.
284 void Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n)
289 } else if (a < seg->addr + seg->szB && seg->szB > 0) {
294 *n = a - (seg->addr + seg->szB);
298 inline Bool Seg__is_freed(Seg* seg)
300 if (!is_known_segment(seg))
303 return seg->nextfree != (Seg*)1;
306 ExeContext* Seg__where(Seg* seg)
308 tl_assert(is_known_segment(seg));
312 SizeT Seg__size(Seg* seg)
314 tl_assert(is_known_segment(seg));
318 Addr Seg__addr(Seg* seg)
320 tl_assert(is_known_segment(seg));
325 #define N_SEGS_PER_GROUP 10000
329 struct _SegGroup* admin;
330 UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */
331 Seg segs[N_SEGS_PER_GROUP];
335 static SegGroup* group_list = NULL;
336 static UWord nFreeSegs = 0;
337 static Seg* freesegs_youngest = NULL;
338 static Seg* freesegs_oldest = NULL;
341 static SegGroup* new_SegGroup ( void ) {
342 SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup));
343 VG_(memset)(g, 0, sizeof(*g));
347 /* Get a completely new Seg */
348 static Seg* new_Seg ( void )
352 if (group_list == NULL) {
357 tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP);
358 if (group_list->nextfree == N_SEGS_PER_GROUP) {
360 g->admin = group_list;
363 tl_assert(group_list->nextfree < N_SEGS_PER_GROUP);
364 teg = &group_list->segs[ group_list->nextfree ];
365 group_list->nextfree++;
366 stats__segs_allocd++;
370 static Seg* get_Seg_for_malloc ( void )
373 if (nFreeSegs < N_FREED_SEGS) {
375 seg->nextfree = (Seg*)1;
378 /* else recycle the oldest Seg in the free list */
379 tl_assert(freesegs_youngest);
380 tl_assert(freesegs_oldest);
381 tl_assert(freesegs_youngest != freesegs_oldest);
382 seg = freesegs_oldest;
383 freesegs_oldest = seg->nextfree;
385 seg->nextfree = (Seg*)1;
386 stats__segs_recycled++;
390 static void set_Seg_freed ( Seg* seg )
393 tl_assert(!Seg__is_freed(seg));
394 if (nFreeSegs == 0) {
395 tl_assert(freesegs_oldest == NULL);
396 tl_assert(freesegs_youngest == NULL);
397 seg->nextfree = NULL;
398 freesegs_youngest = seg;
399 freesegs_oldest = seg;
402 tl_assert(freesegs_youngest);
403 tl_assert(freesegs_oldest);
404 if (nFreeSegs == 1) {
405 tl_assert(freesegs_youngest == freesegs_oldest);
407 tl_assert(freesegs_youngest != freesegs_oldest);
409 tl_assert(freesegs_youngest->nextfree == NULL);
410 tl_assert(seg != freesegs_youngest && seg != freesegs_oldest);
411 seg->nextfree = NULL;
412 freesegs_youngest->nextfree = seg;
413 freesegs_youngest = seg;
418 static WordFM* addr_to_seg_map = NULL; /* GuestAddr -> Seg* */
420 static void addr_to_seg_map_ENSURE_INIT ( void )
422 if (UNLIKELY(addr_to_seg_map == NULL)) {
423 addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1",
424 VG_(free), NULL/*unboxedcmp*/ );
428 static Seg* find_Seg_by_addr ( Addr ga )
431 addr_to_seg_map_ENSURE_INIT();
432 if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) {
433 tl_assert(keyW == ga);
440 static void bind_addr_to_Seg ( Addr ga, Seg* seg )
443 addr_to_seg_map_ENSURE_INIT();
444 b = VG_(addToFM)( addr_to_seg_map, (UWord)ga, (UWord)seg );
445 tl_assert(!b); /* else ga is already bound */
448 static void unbind_addr_from_Seg ( Addr ga )
452 addr_to_seg_map_ENSURE_INIT();
453 b = VG_(delFromFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga );
454 tl_assert(b); /* else ga was not already bound */
455 tl_assert(keyW == ga);
456 tl_assert(valW != 0);
460 //////////////////////////////////////////////////////////////
461 //////////////////////////////////////////////////////////////
462 //////////////////////////////////////////////////////////////
464 // So that post_reg_write_clientcall knows the segment just allocated.
465 static Seg* last_seg_added = NULL;
467 // Returns the added heap segment
468 static Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size )
470 Seg* seg = get_Seg_for_malloc();
471 tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */
474 seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
475 tl_assert(!Seg__is_freed(seg));
477 bind_addr_to_Seg(p, seg);
479 last_seg_added = seg;
484 // Forward declarations
485 static void copy_mem( Addr from, Addr to, SizeT len );
486 static void set_mem_unknown ( Addr a, SizeT len );
488 static inline VG_REGPARM(1) Seg* nonptr_or_unknown(UWord x); /*fwds*/
491 void* alloc_and_new_mem_heap ( ThreadId tid,
492 SizeT size, SizeT alignment, Bool is_zeroed )
496 if ( ((SSizeT)size) < 0) return NULL;
498 p = (Addr)VG_(cli_malloc)(alignment, size);
499 if (is_zeroed) VG_(memset)((void*)p, 0, size);
501 set_mem_unknown( p, size );
502 add_new_segment( tid, p, size );
504 stats__client_mallocs++;
508 static void die_and_free_mem_heap ( ThreadId tid, Seg* seg )
510 // Empty and free the actual block
511 tl_assert(!Seg__is_freed(seg));
512 set_mem_unknown( seg->addr, seg->szB );
514 VG_(cli_free)( (void*)seg->addr );
516 // Remember where freed
517 seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
520 unbind_addr_from_Seg( seg->addr );
522 stats__client_frees++;
525 static void handle_free_heap( ThreadId tid, void* p )
527 Seg* seg = find_Seg_by_addr( (Addr)p );
529 /* freeing a block that wasn't malloc'd. Ignore. */
532 die_and_free_mem_heap( tid, seg );
536 /*------------------------------------------------------------*/
537 /*--- Shadow memory ---*/
538 /*------------------------------------------------------------*/
540 /* Shadow memory holds one Seg for each naturally aligned (guest)
541 word. For a 32 bit target (assuming host word size == guest word
542 size) that means one Seg per 4 bytes, and each Seg occupies 4
543 bytes. For a 64 bit target that means one Seg per 8 bytes, and
544 each Seg occupies 8 bytes. Hence in each case the overall space
545 overhead for shadow memory is 1:1.
547 This does however make it a bit tricky to size SecMap.vseg[], simce
548 it needs to hold 16384 entries for 32 bit targets but only 8192
549 entries for 64 bit targets. */
552 __attribute__((unused))
553 static void pp_curr_ExeContext(void)
557 VG_(get_current_or_recent_tid)() ) );
558 VG_(message)(Vg_UserMsg, "");
562 #if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
563 # define SHMEM_SECMAP_MASK 0xFFFC
564 # define SHMEM_SECMAP_SHIFT 2
565 # define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_4_ALIGNED(_a)
566 # define SEC_MAP_WORDS (0x10000UL / 4UL) /* 16k */
567 #elif defined(VGA_amd64) || defined(VGA_ppc64)
568 # define SHMEM_SECMAP_MASK 0xFFF8
569 # define SHMEM_SECMAP_SHIFT 3
570 # define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_8_ALIGNED(_a)
571 # define SEC_MAP_WORDS (0x10000UL / 8UL) /* 8k */
573 # error "Unknown arch"
578 Seg* vseg[SEC_MAP_WORDS];
582 static SecMap distinguished_secondary_map;
584 /* An entry in the primary map. base must be a 64k-aligned value, and
585 sm points at the relevant secondary map. The secondary may be
586 either a real secondary, or the distinguished secondary. DO NOT
587 CHANGE THIS LAYOUT: the first word has to be the key for OSet fast
597 /* Primary map is an OSet of PriMapEnt (primap_L2), "fronted" by a
598 cache (primap_L1). */
600 /* Tunable parameter: How big is the L1 queue? */
601 #define N_PRIMAP_L1 24
603 /* Tunable parameter: How far along the L1 queue to insert
604 entries resulting from L2 lookups? */
605 #define PRIMAP_L1_INSERT_IX 12
608 Addr base; // must be 64k aligned
609 PriMapEnt* ent; // pointer to the matching primap_L2 node
611 primap_L1[N_PRIMAP_L1];
613 static OSet* primap_L2 = NULL;
616 /* # searches initiated in auxmap_L1, and # base cmps required */
617 static ULong n_primap_L1_searches = 0;
618 static ULong n_primap_L1_cmps = 0;
619 /* # of searches that missed in auxmap_L1 and therefore had to
620 be handed to auxmap_L2. And the number of nodes inserted. */
621 static ULong n_primap_L2_searches = 0;
622 static ULong n_primap_L2_nodes = 0;
625 static void init_shadow_memory ( void )
629 for (i = 0; i < SEC_MAP_WORDS; i++)
630 distinguished_secondary_map.vseg[i] = NONPTR;
632 for (i = 0; i < N_PRIMAP_L1; i++) {
633 primap_L1[i].base = 1; /* not 64k aligned, so doesn't match any
634 request ==> slot is empty */
635 primap_L1[i].ent = NULL;
638 tl_assert(0 == offsetof(PriMapEnt,base));
639 tl_assert(sizeof(Addr) == sizeof(void*));
640 primap_L2 = VG_(OSetGen_Create)( /*keyOff*/ offsetof(PriMapEnt,base),
642 VG_(malloc), "pc.h_main.ism.1",
644 tl_assert(primap_L2);
647 static void insert_into_primap_L1_at ( Word rank, PriMapEnt* ent )
651 tl_assert(rank >= 0 && rank < N_PRIMAP_L1);
652 for (i = N_PRIMAP_L1-1; i > rank; i--)
653 primap_L1[i] = primap_L1[i-1];
654 primap_L1[rank].base = ent->base;
655 primap_L1[rank].ent = ent;
658 static inline PriMapEnt* maybe_find_in_primap ( Addr a )
666 /* First search the front-cache, which is a self-organising
667 list containing the most popular entries. */
669 if (LIKELY(primap_L1[0].base == a))
670 return primap_L1[0].ent;
671 if (LIKELY(primap_L1[1].base == a)) {
672 Addr t_base = primap_L1[0].base;
673 PriMapEnt* t_ent = primap_L1[0].ent;
674 primap_L1[0].base = primap_L1[1].base;
675 primap_L1[0].ent = primap_L1[1].ent;
676 primap_L1[1].base = t_base;
677 primap_L1[1].ent = t_ent;
678 return primap_L1[0].ent;
681 n_primap_L1_searches++;
683 for (i = 0; i < N_PRIMAP_L1; i++) {
684 if (primap_L1[i].base == a) {
688 tl_assert(i >= 0 && i <= N_PRIMAP_L1);
690 n_primap_L1_cmps += (ULong)(i+1);
692 if (i < N_PRIMAP_L1) {
694 Addr t_base = primap_L1[i-1].base;
695 PriMapEnt* t_ent = primap_L1[i-1].ent;
696 primap_L1[i-1].base = primap_L1[i-0].base;
697 primap_L1[i-1].ent = primap_L1[i-0].ent;
698 primap_L1[i-0].base = t_base;
699 primap_L1[i-0].ent = t_ent;
702 return primap_L1[i].ent;
705 n_primap_L2_searches++;
707 /* First see if we already have it. */
711 res = VG_(OSetGen_Lookup)(primap_L2, &key);
713 insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, res );
717 static SecMap* alloc_secondary_map ( void )
722 // JRS 2008-June-25: what's the following assertion for?
723 tl_assert(0 == (sizeof(SecMap) % VKI_MAX_PAGE_SIZE));
725 map = VG_(am_shadow_alloc)( sizeof(SecMap) );
727 VG_(out_of_memory_NORETURN)( "annelid:allocate new SecMap",
730 for (i = 0; i < SEC_MAP_WORDS; i++)
731 map->vseg[i] = NONPTR;
732 if (0) VG_(printf)("XXX new secmap %p\n", map);
736 static PriMapEnt* find_or_alloc_in_primap ( Addr a )
738 PriMapEnt *nyu, *res;
740 /* First see if we already have it. */
741 res = maybe_find_in_primap( a );
745 /* Ok, there's no entry in the secondary map, so we'll have
749 nyu = (PriMapEnt*) VG_(OSetGen_AllocNode)(
750 primap_L2, sizeof(PriMapEnt) );
753 nyu->sm = alloc_secondary_map();
755 VG_(OSetGen_Insert)( primap_L2, nyu );
756 insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, nyu );
761 /////////////////////////////////////////////////
763 // Nb: 'a' must be naturally word aligned for the host.
764 static inline Seg* get_mem_vseg ( Addr a )
766 SecMap* sm = find_or_alloc_in_primap(a)->sm;
767 UWord sm_off = (a & SHMEM_SECMAP_MASK) >> SHMEM_SECMAP_SHIFT;
768 tl_assert(SHMEM_IS_WORD_ALIGNED(a));
769 return sm->vseg[sm_off];
772 // Nb: 'a' must be naturally word aligned for the host.
773 static inline void set_mem_vseg ( Addr a, Seg* vseg )
775 SecMap* sm = find_or_alloc_in_primap(a)->sm;
776 UWord sm_off = (a & SHMEM_SECMAP_MASK) >> SHMEM_SECMAP_SHIFT;
777 tl_assert(SHMEM_IS_WORD_ALIGNED(a));
778 sm->vseg[sm_off] = vseg;
781 // Find the Seg which contains the given address.
782 // Returns UNKNOWN if no matches. Never returns BOTTOM or NONPTR.
783 // Also, only returns in-use segments, not freed ones.
784 /* Doing this fast is distinctly difficult when there are more than a
785 few heap allocated blocks live. Basically it is done by searching
786 addr_to_seg_map for 'a'.
788 First, if 'a' is the start address of a segment, then we can detect
789 that by simply doing a VG_(lookupFM) of 'a', and we are done (nice
792 If 'a' is within some segment, but does not point to the start, it
793 is much more complex. We use VG_(findBoundsFM) to find the segment
794 with the largest .addr field which is <= a, and we then inspect the
795 segment to see if 'a' really falls inside it or not. This is all a
796 bit complex and fragile, and so there's a lot of assertery in the
797 code below. It has been crosschecked however against the trivial
798 _SLOW implementation shown after the end of this fn.
800 static Seg* get_Seg_containing_addr( Addr a )
805 /* Since we are going to poke around in it */
806 addr_to_seg_map_ENSURE_INIT();
808 /* first, see if 'a' is at the start of a block. We do this both
809 because it's easy and more imporantly because VG_(findBoundsFM)
810 will fail in this case, so we need to exclude it first. */
811 if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, a )) {
812 tl_assert(keyW == a);
814 tl_assert(s2->addr == a);
817 UWord kMin, vMin, kMax, vMax;
821 UWord maxAddr = ~minAddr;
822 VG_(memset)(&minSeg, 0, sizeof(minSeg));
823 VG_(memset)(&maxSeg, 0, sizeof(maxSeg));
824 minSeg.addr = minAddr;
825 maxSeg.addr = maxAddr;
826 ok = VG_(findBoundsFM)( addr_to_seg_map,
827 &kMin, &vMin, &kMax, &vMax,
828 minAddr, (UWord)&minSeg,
829 maxAddr, (UWord)&maxSeg, a );
830 tl_assert(ok); /* must be so, since False is only returned when
831 'a' is directly present in the map, and we
832 just established that it isn't. */
833 /* At this point, either vMin points at minSeg, or it points at a
834 real Seg. In the former case, there is no live heap-allocated
835 Seg which has a start address <= a, so a is not in any block.
836 In the latter case, the Seg vMin points at may or may not
837 actually contain 'a'; we can only tell that by inspecting the
840 tl_assert(kMin == s2->addr);
846 tl_assert(s2->addr <= a);
847 /* if s2 doesn't actually contain 'a', we must forget about it. */
848 if (s2->szB == 0 /* a zero sized block can't contain anything */
849 || s2->addr + s2->szB < a /* the usual range check */)
852 /* while we're at it, do as much assertery as we can, since this
853 is all rather complex. Either vMax points at maxSeg, or it
854 points to a real block, which must have a start address
856 tl_assert(kMax == ((Seg*)vMax)->addr);
857 if (vMax == (UWord)&maxSeg) {
858 /* nothing we can check */
860 tl_assert(a < kMax); /* hence also a < ((Seg*)vMax)->addr */
867 /* XXXX very slow reference implementation. Do not use.
868 static Seg* get_Seg_containing_addr_SLOW( Addr a )
872 stats__slow_searches++;
873 for (group = group_list; group; group = group->admin) {
874 for (i = 0; i < group->nextfree; i++) {
875 stats__slow_totcmps++;
876 if (Seg__is_freed(&group->segs[i]))
878 if (group->segs[i].addr <= a
879 && a < group->segs[i].addr + group->segs[i].szB)
880 return &group->segs[i];
889 /*------------------------------------------------------------*/
890 /*--- malloc() et al replacements ---*/
891 /*------------------------------------------------------------*/
893 void* h_replace_malloc ( ThreadId tid, SizeT n )
895 return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
896 /*is_zeroed*/False );
899 void* h_replace___builtin_new ( ThreadId tid, SizeT n )
901 return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
902 /*is_zeroed*/False );
905 void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
907 return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
908 /*is_zeroed*/False );
911 void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
913 return alloc_and_new_mem_heap ( tid, n, align,
914 /*is_zeroed*/False );
917 void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
919 return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
923 void h_replace_free ( ThreadId tid, void* p )
925 // Should arguably check here if p.vseg matches the segID of the
926 // pointed-to block... unfortunately, by this stage, we don't know what
927 // p.vseg is, because we don't know the address of p (the p here is a
928 // copy, and we've lost the address of its source). To do so would
929 // require passing &p in, which would require rewriting part of
930 // vg_replace_malloc.c... argh.
932 // However, Memcheck does free checking, and will catch almost all
933 // violations this checking would have caught. (Would only miss if we
934 // unluckily passed an unrelated pointer to the very start of a heap
935 // block that was unrelated to that block. This is very unlikely!) So
936 // we haven't lost much.
938 handle_free_heap(tid, p);
941 void h_replace___builtin_delete ( ThreadId tid, void* p )
943 handle_free_heap(tid, p);
946 void h_replace___builtin_vec_delete ( ThreadId tid, void* p )
948 handle_free_heap(tid, p);
951 void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
955 /* First try and find the block. */
956 seg = find_Seg_by_addr( (Addr)p_old );
960 tl_assert(seg->addr == (Addr)p_old);
962 if (new_size <= seg->szB) {
963 /* new size is smaller: allocate, copy from old to new */
964 Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
965 VG_(memcpy)((void*)p_new, p_old, new_size);
967 /* Notification: copy retained part */
968 copy_mem ( (Addr)p_old, p_new, new_size );
970 /* Free old memory */
971 die_and_free_mem_heap( tid, seg );
973 /* This has to be after die_and_free_mem_heap, otherwise the
974 former succeeds in shorting out the new block, not the
975 old, in the case when both are on the same list. */
976 add_new_segment ( tid, p_new, new_size );
980 /* new size is bigger: allocate, copy from old to new */
981 Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
982 VG_(memcpy)((void*)p_new, p_old, seg->szB);
984 /* Notification: first half kept and copied, second half new */
985 copy_mem ( (Addr)p_old, p_new, seg->szB );
986 set_mem_unknown( p_new + seg->szB, new_size - seg->szB );
988 /* Free old memory */
989 die_and_free_mem_heap( tid, seg );
991 /* This has to be after die_and_free_mem_heap, otherwise the
992 former succeeds in shorting out the new block, not the old,
993 in the case when both are on the same list. NB jrs
994 2008-Sept-11: not sure if this comment is valid/correct any
995 more -- I suspect not. */
996 add_new_segment ( tid, p_new, new_size );
1002 SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p )
1004 Seg* seg = find_Seg_by_addr( (Addr)p );
1006 // There may be slop, but pretend there isn't because only the asked-for
1007 // area will have been shadowed properly.
1008 return ( seg ? seg->szB : 0 );
1012 /*------------------------------------------------------------*/
1013 /*--- Memory events ---*/
1014 /*------------------------------------------------------------*/
1017 void set_mem ( Addr a, SizeT len, Seg* seg )
1024 if (len > 100 * 1000 * 1000)
1025 VG_(message)(Vg_UserMsg,
1026 "Warning: set address range state: large range %lu\n",
1029 a = VG_ROUNDDN(a, sizeof(UWord));
1030 end = VG_ROUNDUP(a + len, sizeof(UWord));
1031 for ( ; a < end; a += sizeof(UWord))
1032 set_mem_vseg(a, seg);
1035 static void set_mem_unknown( Addr a, SizeT len )
1037 set_mem( a, len, UNKNOWN );
1040 //zz static void set_mem_nonptr( Addr a, UInt len )
1042 //zz set_mem( a, len, NONPTR );
1045 void h_new_mem_startup( Addr a, SizeT len,
1046 Bool rr, Bool ww, Bool xx, ULong di_handle )
1048 if (0) VG_(printf)("new_mem_startup(%#lx,%lu)\n", a, len);
1049 set_mem_unknown( a, len );
1050 //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1053 //zz // XXX: Currently not doing anything with brk() -- new segments, or not?
1054 //zz // Proper way to do it would be to grow/shrink a single, special brk segment.
1056 //zz // brk is difficult: it defines a single segment, of changeable size.
1057 //zz // It starts off with size zero, at the address given by brk(0). There are
1058 //zz // no pointers within the program to it. Any subsequent calls by the
1059 //zz // program to brk() (possibly growing or shrinking it) return pointers to
1060 //zz // the *end* of the segment (nb: this is the kernel brk(), which is
1061 //zz // different to the libc brk()).
1063 //zz // If fixing this, don't forget to update the brk case in SK_(post_syscall).
1065 //zz // Nb: not sure if the return value is the last byte addressible, or one
1066 //zz // past the end of the segment.
1068 //zz static void new_mem_brk( Addr a, UInt len )
1070 //zz set_mem_unknown(a, len);
1071 //zz //VG_(skin_panic)("can't handle new_mem_brk");
1074 // Not quite right: if you mmap a segment into a specified place, it could
1075 // be legitimate to do certain arithmetic with the pointer that it wouldn't
1076 // otherwise. Hopefully this is rare, though.
1077 void h_new_mem_mmap( Addr a, SizeT len,
1078 Bool rr, Bool ww, Bool xx, ULong di_handle )
1080 if (0) VG_(printf)("new_mem_mmap(%#lx,%lu)\n", a, len);
1082 //zz Seg seg = NULL;
1084 //zz // Check for overlapping segments
1086 //zz is_overlapping_seg___a = a; // 'free' variable
1087 //zz is_overlapping_seg___len = len; // 'free' variable
1088 //zz seg = (Seg)VG_(HT_first_match) ( mlist, is_overlapping_seg );
1089 //zz is_overlapping_seg___a = 0; // paranoia, reset
1090 //zz is_overlapping_seg___len = 0; // paranoia, reset
1093 //zz // XXX: do this check properly with ISLists
1095 //zz if ( ISList__findI( seglist, a, &seg )) {
1096 //zz sk_assert(SegMmap == seg->status || SegMmapFree == seg->status);
1097 //zz if (SegMmap == seg->status)
1101 //zz if (NULL != seg) {
1102 //zz // Right, we found an overlap
1103 //zz if (VG_(clo_verbosity) > 1)
1104 //zz VG_(message)(Vg_UserMsg, "mmap overlap: old: %#lx, %d; new: %#lx, %d",
1105 //zz seg->left, Seg__size(seg), a, len);
1106 //zz if (seg->left <= a && a <= seg->right) {
1107 //zz // New one truncates end of the old one. Nb: we don't adjust its
1108 //zz // size, because the first segment's pointer can be (and for
1109 //zz // Konqueror, is) legitimately used to access parts of the second
1110 //zz // segment. At least, I assume Konqueror is doing something legal.
1111 //zz // so that a size mismatch upon munmap isn't a problem.
1112 //zz // seg->size = a - seg->data;
1113 //zz // seg->is_truncated_map = True;
1114 //zz // if (VG_(clo_verbosity) > 1)
1115 //zz // VG_(message)(Vg_UserMsg, "old seg truncated to length %d",
1118 //zz VG_(skin_panic)("Can't handle this mmap() overlap case");
1121 set_mem_unknown( a, len );
1122 //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1126 static void copy_mem( Addr from, Addr to, SizeT len )
1128 Addr fromend = from + len;
1130 // Must be aligned due to malloc always returning aligned objects.
1131 tl_assert(VG_IS_8_ALIGNED(from) && VG_IS_8_ALIGNED(to));
1133 // Must only be called with positive len.
1137 for ( ; from < fromend; from += sizeof(UWord), to += sizeof(UWord))
1138 set_mem_vseg( to, get_mem_vseg(from) );
1141 //zz // Similar to SK_(realloc)()
1142 //zz static void copy_mem_remap( Addr from, Addr to, UInt len )
1144 //zz VG_(skin_panic)("argh: copy_mem_remap");
1147 //zz static void die_mem_brk( Addr a, UInt len )
1149 //zz set_mem_unknown(a, len);
1150 //zz // VG_(skin_panic)("can't handle die_mem_brk()");
1153 void h_die_mem_munmap( Addr a, SizeT len )
1155 // handle_free_munmap( (void*)a, len );
1158 // Don't need to check all addresses within the block; in the absence of
1159 // discontiguous segments, the segments for the first and last bytes should
1160 // be the same. Can't easily check the pointer segment matches the block
1161 // segment, unfortunately, but the first/last check should catch most
1163 static void pre_mem_access2 ( CorePart part, ThreadId tid, Char* str,
1164 Addr s/*tart*/, Addr e/*nd*/ )
1168 // Don't check code being translated -- very slow, and not much point
1169 if (Vg_CoreTranslate == part) return;
1171 // Don't check the signal case -- only happens in core, no need to check
1172 if (Vg_CoreSignal == part) return;
1174 // Only expect syscalls after this point
1175 if (part != Vg_CoreSysCall) {
1176 VG_(printf)("part = %d\n", part);
1177 VG_(tool_panic)("unknown corepart in pre_mem_access2");
1180 // Check first and last bytes match
1181 seglo = get_Seg_containing_addr( s );
1182 seghi = get_Seg_containing_addr( e );
1183 tl_assert( BOTTOM != seglo && NONPTR != seglo );
1184 tl_assert( BOTTOM != seghi && NONPTR != seghi );
1186 /* record an error if start and end are in different, but known segments */
1187 if (is_known_segment(seglo) && is_known_segment(seghi)
1188 && seglo != seghi) {
1189 h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
1192 /* record an error if start is in a known segment but end isn't */
1193 if (is_known_segment(seglo) && !is_known_segment(seghi)) {
1194 h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
1197 /* record an error if end is in a known segment but start isn't */
1198 if (!is_known_segment(seglo) && is_known_segment(seghi)) {
1199 h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi);
1203 void h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
1204 Addr base, SizeT size )
1206 pre_mem_access2( part, tid, s, base, base + size - 1 );
1209 void h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
1214 // Nb: the '\0' must be included in the lo...hi range
1215 while ('\0' != *(Char*)hi) hi++;
1216 pre_mem_access2( part, tid, s, lo, hi );
1219 //zz static void post_mem_write(Addr a, UInt len)
1221 //zz set_mem_unknown(a, len);
1225 /*------------------------------------------------------------*/
1226 /*--- Register event handlers ---*/
1227 /*------------------------------------------------------------*/
1229 //zz static void post_regs_write_init ( void )
1232 //zz for (i = R_EAX; i <= R_EDI; i++)
1233 //zz VG_(set_shadow_archreg)( i, (UInt)UNKNOWN );
1235 //zz // Don't bother about eflags
1238 // BEGIN move this uglyness to pc_machine.c
1240 static inline Bool host_is_big_endian ( void ) {
1241 UInt x = 0x11223344;
1242 return 0x1122 == *(UShort*)(&x);
1244 static inline Bool host_is_little_endian ( void ) {
1245 UInt x = 0x11223344;
1246 return 0x3344 == *(UShort*)(&x);
1249 #define N_INTREGINFO_OFFSETS 4
1251 /* Holds the result of a query to 'get_IntRegInfo'. Valid values for
1254 -1: means the queried guest state slice exactly matches
1255 one integer register
1257 0: means the queried guest state slice does not overlap any
1260 1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset
1261 overlaps n_offsets different integer registers, and their base
1262 offsets are placed in the offsets array.
1266 Int offsets[N_INTREGINFO_OFFSETS];
1272 #if defined(VGA_x86)
1273 # include "libvex_guest_x86.h"
1274 # define PC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State)
1277 #if defined(VGA_amd64)
1278 # include "libvex_guest_amd64.h"
1279 # define PC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State)
1280 # define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO)
1281 # define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO)
1284 #if defined(VGA_ppc32)
1285 # include "libvex_guest_ppc32.h"
1286 # define PC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State)
1289 #if defined(VGA_ppc64)
1290 # include "libvex_guest_ppc64.h"
1291 # define PC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
1294 #if defined(VGA_arm)
1295 # include "libvex_guest_arm.h"
1296 # define PC_SIZEOF_GUEST_STATE sizeof(VexGuestARMState)
1300 /* See description on definition of type IntRegInfo. */
1301 static void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
1303 /* --------------------- x86 --------------------- */
1305 # if defined(VGA_x86)
1307 # define GOF(_fieldname) \
1308 (offsetof(VexGuestX86State,guest_##_fieldname))
1313 Bool is21 = sz == 2 || sz == 1;
1316 tl_assert(host_is_little_endian());
1318 /* Set default state to "does not intersect any int register". */
1319 VG_(memset)( iii, 0, sizeof(*iii) );
1321 /* Exact accesses to integer registers */
1322 if (o == GOF(EAX) && is4) goto exactly1;
1323 if (o == GOF(ECX) && is4) goto exactly1;
1324 if (o == GOF(EDX) && is4) goto exactly1;
1325 if (o == GOF(EBX) && is4) goto exactly1;
1326 if (o == GOF(ESP) && is4) goto exactly1;
1327 if (o == GOF(EBP) && is4) goto exactly1;
1328 if (o == GOF(ESI) && is4) goto exactly1;
1329 if (o == GOF(EDI) && is4) goto exactly1;
1330 if (o == GOF(EIP) && is4) goto none;
1331 if (o == GOF(IP_AT_SYSCALL) && is4) goto none;
1332 if (o == GOF(CC_OP) && is4) goto none;
1333 if (o == GOF(CC_DEP1) && is4) goto none;
1334 if (o == GOF(CC_DEP2) && is4) goto none;
1335 if (o == GOF(CC_NDEP) && is4) goto none;
1336 if (o == GOF(DFLAG) && is4) goto none;
1337 if (o == GOF(IDFLAG) && is4) goto none;
1338 if (o == GOF(ACFLAG) && is4) goto none;
1340 /* Partial accesses to integer registers */
1341 if (o == GOF(EAX) && is21) { o -= 0; goto contains_o; }
1342 if (o == GOF(EAX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1343 if (o == GOF(ECX) && is21) { o -= 0; goto contains_o; }
1344 if (o == GOF(ECX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1345 if (o == GOF(EBX) && is21) { o -= 0; goto contains_o; }
1346 if (o == GOF(EBX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1347 if (o == GOF(EDX) && is21) { o -= 0; goto contains_o; }
1348 if (o == GOF(EDX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1349 if (o == GOF(ESI) && is21) { o -= 0; goto contains_o; }
1350 if (o == GOF(EDI) && is21) { o -= 0; goto contains_o; }
1352 /* Segment related guff */
1353 if (o == GOF(GS) && sz == 2) goto none;
1354 if (o == GOF(LDT) && is4) goto none;
1355 if (o == GOF(GDT) && is4) goto none;
1357 /* FP admin related */
1358 if (o == GOF(SSEROUND) && is4) goto none;
1359 if (o == GOF(FPROUND) && is4) goto none;
1360 if (o == GOF(EMWARN) && is4) goto none;
1361 if (o == GOF(FTOP) && is4) goto none;
1362 if (o == GOF(FPTAG) && sz == 8) goto none;
1363 if (o == GOF(FC3210) && is4) goto none;
1365 /* xmm registers, including arbitrary sub-parts */
1366 if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1367 if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1368 if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1369 if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1370 if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1371 if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1372 if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1373 if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1375 /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1376 to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1377 if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1379 /* the entire mmx/x87 register bank in one big piece */
1380 if (o == GOF(FPREG) && sz == 64) goto none;
1382 VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz);
1386 /* -------------------- amd64 -------------------- */
1388 # elif defined(VGA_amd64)
1390 # define GOF(_fieldname) \
1391 (offsetof(VexGuestAMD64State,guest_##_fieldname))
1395 Bool is421 = sz == 4 || sz == 2 || sz == 1;
1399 tl_assert(host_is_little_endian());
1401 /* Set default state to "does not intersect any int register". */
1402 VG_(memset)( iii, 0, sizeof(*iii) );
1404 /* Exact accesses to integer registers */
1405 if (o == GOF(RAX) && is8) goto exactly1;
1406 if (o == GOF(RCX) && is8) goto exactly1;
1407 if (o == GOF(RDX) && is8) goto exactly1;
1408 if (o == GOF(RBX) && is8) goto exactly1;
1409 if (o == GOF(RSP) && is8) goto exactly1;
1410 if (o == GOF(RBP) && is8) goto exactly1;
1411 if (o == GOF(RSI) && is8) goto exactly1;
1412 if (o == GOF(RDI) && is8) goto exactly1;
1413 if (o == GOF(R8) && is8) goto exactly1;
1414 if (o == GOF(R9) && is8) goto exactly1;
1415 if (o == GOF(R10) && is8) goto exactly1;
1416 if (o == GOF(R11) && is8) goto exactly1;
1417 if (o == GOF(R12) && is8) goto exactly1;
1418 if (o == GOF(R13) && is8) goto exactly1;
1419 if (o == GOF(R14) && is8) goto exactly1;
1420 if (o == GOF(R15) && is8) goto exactly1;
1421 if (o == GOF(RIP) && is8) goto exactly1;
1422 if (o == GOF(IP_AT_SYSCALL) && is8) goto none;
1423 if (o == GOF(CC_OP) && is8) goto none;
1424 if (o == GOF(CC_DEP1) && is8) goto none;
1425 if (o == GOF(CC_DEP2) && is8) goto none;
1426 if (o == GOF(CC_NDEP) && is8) goto none;
1427 if (o == GOF(DFLAG) && is8) goto none;
1428 if (o == GOF(IDFLAG) && is8) goto none;
1430 /* Partial accesses to integer registers */
1431 if (o == GOF(RAX) && is421) { o -= 0; goto contains_o; }
1432 if (o == GOF(RAX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1433 if (o == GOF(RCX) && is421) { o -= 0; goto contains_o; }
1434 if (o == GOF(RCX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1435 if (o == GOF(RDX) && is421) { o -= 0; goto contains_o; }
1436 if (o == GOF(RDX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1437 if (o == GOF(RBX) && is421) { o -= 0; goto contains_o; }
1438 if (o == GOF(RBX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1439 if (o == GOF(RBP) && is421) { o -= 0; goto contains_o; }
1440 if (o == GOF(RSI) && is421) { o -= 0; goto contains_o; }
1441 if (o == GOF(RDI) && is421) { o -= 0; goto contains_o; }
1442 if (o == GOF(R8) && is421) { o -= 0; goto contains_o; }
1443 if (o == GOF(R9) && is421) { o -= 0; goto contains_o; }
1444 if (o == GOF(R10) && is421) { o -= 0; goto contains_o; }
1445 if (o == GOF(R11) && is421) { o -= 0; goto contains_o; }
1446 if (o == GOF(R12) && is421) { o -= 0; goto contains_o; }
1447 if (o == GOF(R13) && is421) { o -= 0; goto contains_o; }
1448 if (o == GOF(R14) && is421) { o -= 0; goto contains_o; }
1449 if (o == GOF(R15) && is421) { o -= 0; goto contains_o; }
1451 /* Segment related guff */
1452 if (o == GOF(FS_ZERO) && is8) goto exactly1;
1454 /* FP admin related */
1455 if (o == GOF(SSEROUND) && is8) goto none;
1456 if (o == GOF(FPROUND) && is8) goto none;
1457 if (o == GOF(EMWARN) && sz == 4) goto none;
1458 if (o == GOF(FTOP) && sz == 4) goto none;
1459 if (o == GOF(FPTAG) && is8) goto none;
1460 if (o == GOF(FC3210) && is8) goto none;
1462 /* xmm registers, including arbitrary sub-parts */
1463 if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1464 if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1465 if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1466 if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1467 if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1468 if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1469 if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1470 if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1471 if (o >= GOF(XMM8) && o+sz <= GOF(XMM8)+16) goto none;
1472 if (o >= GOF(XMM9) && o+sz <= GOF(XMM9)+16) goto none;
1473 if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none;
1474 if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none;
1475 if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none;
1476 if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none;
1477 if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none;
1478 if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none;
1480 /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1481 to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1482 if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1484 VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz);
1488 /* -------------------- ppc32 -------------------- */
1490 # elif defined(VGA_ppc32)
1492 # define GOF(_fieldname) \
1493 (offsetof(VexGuestPPC32State,guest_##_fieldname))
1501 tl_assert(host_is_big_endian());
1503 /* Set default state to "does not intersect any int register". */
1504 VG_(memset)( iii, 0, sizeof(*iii) );
1506 /* Exact accesses to integer registers */
1507 if (o == GOF(GPR0) && is4) goto exactly1;
1508 if (o == GOF(GPR1) && is4) goto exactly1;
1509 if (o == GOF(GPR2) && is4) goto exactly1;
1510 if (o == GOF(GPR3) && is4) goto exactly1;
1511 if (o == GOF(GPR4) && is4) goto exactly1;
1512 if (o == GOF(GPR5) && is4) goto exactly1;
1513 if (o == GOF(GPR6) && is4) goto exactly1;
1514 if (o == GOF(GPR7) && is4) goto exactly1;
1515 if (o == GOF(GPR8) && is4) goto exactly1;
1516 if (o == GOF(GPR9) && is4) goto exactly1;
1517 if (o == GOF(GPR10) && is4) goto exactly1;
1518 if (o == GOF(GPR11) && is4) goto exactly1;
1519 if (o == GOF(GPR12) && is4) goto exactly1;
1520 if (o == GOF(GPR13) && is4) goto exactly1;
1521 if (o == GOF(GPR14) && is4) goto exactly1;
1522 if (o == GOF(GPR15) && is4) goto exactly1;
1523 if (o == GOF(GPR16) && is4) goto exactly1;
1524 if (o == GOF(GPR17) && is4) goto exactly1;
1525 if (o == GOF(GPR18) && is4) goto exactly1;
1526 if (o == GOF(GPR19) && is4) goto exactly1;
1527 if (o == GOF(GPR20) && is4) goto exactly1;
1528 if (o == GOF(GPR21) && is4) goto exactly1;
1529 if (o == GOF(GPR22) && is4) goto exactly1;
1530 if (o == GOF(GPR23) && is4) goto exactly1;
1531 if (o == GOF(GPR24) && is4) goto exactly1;
1532 if (o == GOF(GPR25) && is4) goto exactly1;
1533 if (o == GOF(GPR26) && is4) goto exactly1;
1534 if (o == GOF(GPR27) && is4) goto exactly1;
1535 if (o == GOF(GPR28) && is4) goto exactly1;
1536 if (o == GOF(GPR29) && is4) goto exactly1;
1537 if (o == GOF(GPR30) && is4) goto exactly1;
1538 if (o == GOF(GPR31) && is4) goto exactly1;
1540 /* Misc integer reg and condition code accesses */
1541 if (o == GOF(LR) && is4) goto exactly1;
1542 if (o == GOF(CTR) && is4) goto exactly1;
1543 if (o == GOF(CIA) && is4) goto none;
1544 if (o == GOF(IP_AT_SYSCALL) && is4) goto none;
1545 if (o == GOF(TISTART) && is4) goto none;
1546 if (o == GOF(TILEN) && is4) goto none;
1547 if (o == GOF(REDIR_SP) && is4) goto none;
1550 if (o == GOF(XER_SO)) goto none;
1551 if (o == GOF(XER_OV)) goto none;
1552 if (o == GOF(XER_CA)) goto none;
1553 if (o == GOF(XER_BC)) goto none;
1554 if (o == GOF(CR0_321)) goto none;
1555 if (o == GOF(CR0_0)) goto none;
1556 if (o == GOF(CR1_321)) goto none;
1557 if (o == GOF(CR1_0)) goto none;
1558 if (o == GOF(CR2_321)) goto none;
1559 if (o == GOF(CR2_0)) goto none;
1560 if (o == GOF(CR3_321)) goto none;
1561 if (o == GOF(CR3_0)) goto none;
1562 if (o == GOF(CR4_321)) goto none;
1563 if (o == GOF(CR4_0)) goto none;
1564 if (o == GOF(CR5_321)) goto none;
1565 if (o == GOF(CR5_0)) goto none;
1566 if (o == GOF(CR6_321)) goto none;
1567 if (o == GOF(CR6_0)) goto none;
1568 if (o == GOF(CR7_321)) goto none;
1569 if (o == GOF(CR7_0)) goto none;
1572 /* Exact accesses to FP registers */
1573 if (o == GOF(FPR0) && is8) goto none;
1574 if (o == GOF(FPR1) && is8) goto none;
1575 if (o == GOF(FPR2) && is8) goto none;
1576 if (o == GOF(FPR3) && is8) goto none;
1577 if (o == GOF(FPR4) && is8) goto none;
1578 if (o == GOF(FPR5) && is8) goto none;
1579 if (o == GOF(FPR6) && is8) goto none;
1580 if (o == GOF(FPR7) && is8) goto none;
1581 if (o == GOF(FPR8) && is8) goto none;
1582 if (o == GOF(FPR9) && is8) goto none;
1583 if (o == GOF(FPR10) && is8) goto none;
1584 if (o == GOF(FPR11) && is8) goto none;
1585 if (o == GOF(FPR12) && is8) goto none;
1586 if (o == GOF(FPR13) && is8) goto none;
1587 if (o == GOF(FPR14) && is8) goto none;
1588 if (o == GOF(FPR15) && is8) goto none;
1589 if (o == GOF(FPR16) && is8) goto none;
1590 if (o == GOF(FPR17) && is8) goto none;
1591 if (o == GOF(FPR18) && is8) goto none;
1592 if (o == GOF(FPR19) && is8) goto none;
1593 if (o == GOF(FPR20) && is8) goto none;
1594 if (o == GOF(FPR21) && is8) goto none;
1595 if (o == GOF(FPR22) && is8) goto none;
1596 if (o == GOF(FPR23) && is8) goto none;
1597 if (o == GOF(FPR24) && is8) goto none;
1598 if (o == GOF(FPR25) && is8) goto none;
1599 if (o == GOF(FPR26) && is8) goto none;
1600 if (o == GOF(FPR27) && is8) goto none;
1601 if (o == GOF(FPR28) && is8) goto none;
1602 if (o == GOF(FPR29) && is8) goto none;
1603 if (o == GOF(FPR30) && is8) goto none;
1604 if (o == GOF(FPR31) && is8) goto none;
1606 /* FP admin related */
1607 if (o == GOF(FPROUND) && is4) goto none;
1608 if (o == GOF(EMWARN) && is4) goto none;
1610 /* Altivec registers */
1611 if (o == GOF(VR0) && sz == 16) goto none;
1612 if (o == GOF(VR1) && sz == 16) goto none;
1613 if (o == GOF(VR2) && sz == 16) goto none;
1614 if (o == GOF(VR3) && sz == 16) goto none;
1615 if (o == GOF(VR4) && sz == 16) goto none;
1616 if (o == GOF(VR5) && sz == 16) goto none;
1617 if (o == GOF(VR6) && sz == 16) goto none;
1618 if (o == GOF(VR7) && sz == 16) goto none;
1619 if (o == GOF(VR8) && sz == 16) goto none;
1620 if (o == GOF(VR9) && sz == 16) goto none;
1621 if (o == GOF(VR10) && sz == 16) goto none;
1622 if (o == GOF(VR11) && sz == 16) goto none;
1623 if (o == GOF(VR12) && sz == 16) goto none;
1624 if (o == GOF(VR13) && sz == 16) goto none;
1625 if (o == GOF(VR14) && sz == 16) goto none;
1626 if (o == GOF(VR15) && sz == 16) goto none;
1627 if (o == GOF(VR16) && sz == 16) goto none;
1628 if (o == GOF(VR17) && sz == 16) goto none;
1629 if (o == GOF(VR18) && sz == 16) goto none;
1630 if (o == GOF(VR19) && sz == 16) goto none;
1631 if (o == GOF(VR20) && sz == 16) goto none;
1632 if (o == GOF(VR21) && sz == 16) goto none;
1633 if (o == GOF(VR22) && sz == 16) goto none;
1634 if (o == GOF(VR23) && sz == 16) goto none;
1635 if (o == GOF(VR24) && sz == 16) goto none;
1636 if (o == GOF(VR25) && sz == 16) goto none;
1637 if (o == GOF(VR26) && sz == 16) goto none;
1638 if (o == GOF(VR27) && sz == 16) goto none;
1639 if (o == GOF(VR28) && sz == 16) goto none;
1640 if (o == GOF(VR29) && sz == 16) goto none;
1641 if (o == GOF(VR30) && sz == 16) goto none;
1642 if (o == GOF(VR31) && sz == 16) goto none;
1644 /* Altivec admin related */
1645 if (o == GOF(VRSAVE) && is4) goto none;
1647 VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz);
1651 /* -------------------- ppc64 -------------------- */
1653 # elif defined(VGA_ppc64)
1655 # define GOF(_fieldname) \
1656 (offsetof(VexGuestPPC64State,guest_##_fieldname))
1664 tl_assert(host_is_big_endian());
1666 /* Set default state to "does not intersect any int register". */
1667 VG_(memset)( iii, 0, sizeof(*iii) );
1669 /* Exact accesses to integer registers */
1670 if (o == GOF(GPR0) && is8) goto exactly1;
1671 if (o == GOF(GPR1) && is8) goto exactly1;
1672 if (o == GOF(GPR2) && is8) goto exactly1;
1673 if (o == GOF(GPR3) && is8) goto exactly1;
1674 if (o == GOF(GPR4) && is8) goto exactly1;
1675 if (o == GOF(GPR5) && is8) goto exactly1;
1676 if (o == GOF(GPR6) && is8) goto exactly1;
1677 if (o == GOF(GPR7) && is8) goto exactly1;
1678 if (o == GOF(GPR8) && is8) goto exactly1;
1679 if (o == GOF(GPR9) && is8) goto exactly1;
1680 if (o == GOF(GPR10) && is8) goto exactly1;
1681 if (o == GOF(GPR11) && is8) goto exactly1;
1682 if (o == GOF(GPR12) && is8) goto exactly1;
1683 if (o == GOF(GPR13) && is8) goto exactly1;
1684 if (o == GOF(GPR14) && is8) goto exactly1;
1685 if (o == GOF(GPR15) && is8) goto exactly1;
1686 if (o == GOF(GPR16) && is8) goto exactly1;
1687 if (o == GOF(GPR17) && is8) goto exactly1;
1688 if (o == GOF(GPR18) && is8) goto exactly1;
1689 if (o == GOF(GPR19) && is8) goto exactly1;
1690 if (o == GOF(GPR20) && is8) goto exactly1;
1691 if (o == GOF(GPR21) && is8) goto exactly1;
1692 if (o == GOF(GPR22) && is8) goto exactly1;
1693 if (o == GOF(GPR23) && is8) goto exactly1;
1694 if (o == GOF(GPR24) && is8) goto exactly1;
1695 if (o == GOF(GPR25) && is8) goto exactly1;
1696 if (o == GOF(GPR26) && is8) goto exactly1;
1697 if (o == GOF(GPR27) && is8) goto exactly1;
1698 if (o == GOF(GPR28) && is8) goto exactly1;
1699 if (o == GOF(GPR29) && is8) goto exactly1;
1700 if (o == GOF(GPR30) && is8) goto exactly1;
1701 if (o == GOF(GPR31) && is8) goto exactly1;
1703 /* Misc integer reg and condition code accesses */
1704 if (o == GOF(LR) && is8) goto exactly1;
1705 if (o == GOF(CTR) && is8) goto exactly1;
1706 if (o == GOF(CIA) && is8) goto none;
1707 if (o == GOF(IP_AT_SYSCALL) && is8) goto none;
1708 if (o == GOF(TISTART) && is8) goto none;
1709 if (o == GOF(TILEN) && is8) goto none;
1710 if (o == GOF(REDIR_SP) && is8) goto none;
1713 if (o == GOF(XER_SO)) goto none;
1714 if (o == GOF(XER_OV)) goto none;
1715 if (o == GOF(XER_CA)) goto none;
1716 if (o == GOF(XER_BC)) goto none;
1717 if (o == GOF(CR0_321)) goto none;
1718 if (o == GOF(CR0_0)) goto none;
1719 if (o == GOF(CR1_321)) goto none;
1720 if (o == GOF(CR1_0)) goto none;
1721 if (o == GOF(CR2_321)) goto none;
1722 if (o == GOF(CR2_0)) goto none;
1723 if (o == GOF(CR3_321)) goto none;
1724 if (o == GOF(CR3_0)) goto none;
1725 if (o == GOF(CR4_321)) goto none;
1726 if (o == GOF(CR4_0)) goto none;
1727 if (o == GOF(CR5_321)) goto none;
1728 if (o == GOF(CR5_0)) goto none;
1729 if (o == GOF(CR6_321)) goto none;
1730 if (o == GOF(CR6_0)) goto none;
1731 if (o == GOF(CR7_321)) goto none;
1732 if (o == GOF(CR7_0)) goto none;
1735 /* Exact accesses to FP registers */
1736 if (o == GOF(FPR0) && is8) goto none;
1737 if (o == GOF(FPR1) && is8) goto none;
1738 if (o == GOF(FPR2) && is8) goto none;
1739 if (o == GOF(FPR3) && is8) goto none;
1740 if (o == GOF(FPR4) && is8) goto none;
1741 if (o == GOF(FPR5) && is8) goto none;
1742 if (o == GOF(FPR6) && is8) goto none;
1743 if (o == GOF(FPR7) && is8) goto none;
1744 if (o == GOF(FPR8) && is8) goto none;
1745 if (o == GOF(FPR9) && is8) goto none;
1746 if (o == GOF(FPR10) && is8) goto none;
1747 if (o == GOF(FPR11) && is8) goto none;
1748 if (o == GOF(FPR12) && is8) goto none;
1749 if (o == GOF(FPR13) && is8) goto none;
1750 if (o == GOF(FPR14) && is8) goto none;
1751 if (o == GOF(FPR15) && is8) goto none;
1752 if (o == GOF(FPR16) && is8) goto none;
1753 if (o == GOF(FPR17) && is8) goto none;
1754 if (o == GOF(FPR18) && is8) goto none;
1755 if (o == GOF(FPR19) && is8) goto none;
1756 if (o == GOF(FPR20) && is8) goto none;
1757 if (o == GOF(FPR21) && is8) goto none;
1758 if (o == GOF(FPR22) && is8) goto none;
1759 if (o == GOF(FPR23) && is8) goto none;
1760 if (o == GOF(FPR24) && is8) goto none;
1761 if (o == GOF(FPR25) && is8) goto none;
1762 if (o == GOF(FPR26) && is8) goto none;
1763 if (o == GOF(FPR27) && is8) goto none;
1764 if (o == GOF(FPR28) && is8) goto none;
1765 if (o == GOF(FPR29) && is8) goto none;
1766 if (o == GOF(FPR30) && is8) goto none;
1767 if (o == GOF(FPR31) && is8) goto none;
1769 /* FP admin related */
1770 if (o == GOF(FPROUND) && is4) goto none;
1771 if (o == GOF(EMWARN) && is4) goto none;
1773 /* Altivec registers */
1774 if (o == GOF(VR0) && sz == 16) goto none;
1775 if (o == GOF(VR1) && sz == 16) goto none;
1776 if (o == GOF(VR2) && sz == 16) goto none;
1777 if (o == GOF(VR3) && sz == 16) goto none;
1778 if (o == GOF(VR4) && sz == 16) goto none;
1779 if (o == GOF(VR5) && sz == 16) goto none;
1780 if (o == GOF(VR6) && sz == 16) goto none;
1781 if (o == GOF(VR7) && sz == 16) goto none;
1782 if (o == GOF(VR8) && sz == 16) goto none;
1783 if (o == GOF(VR9) && sz == 16) goto none;
1784 if (o == GOF(VR10) && sz == 16) goto none;
1785 if (o == GOF(VR11) && sz == 16) goto none;
1786 if (o == GOF(VR12) && sz == 16) goto none;
1787 if (o == GOF(VR13) && sz == 16) goto none;
1788 if (o == GOF(VR14) && sz == 16) goto none;
1789 if (o == GOF(VR15) && sz == 16) goto none;
1790 if (o == GOF(VR16) && sz == 16) goto none;
1791 if (o == GOF(VR17) && sz == 16) goto none;
1792 if (o == GOF(VR18) && sz == 16) goto none;
1793 if (o == GOF(VR19) && sz == 16) goto none;
1794 if (o == GOF(VR20) && sz == 16) goto none;
1795 if (o == GOF(VR21) && sz == 16) goto none;
1796 if (o == GOF(VR22) && sz == 16) goto none;
1797 if (o == GOF(VR23) && sz == 16) goto none;
1798 if (o == GOF(VR24) && sz == 16) goto none;
1799 if (o == GOF(VR25) && sz == 16) goto none;
1800 if (o == GOF(VR26) && sz == 16) goto none;
1801 if (o == GOF(VR27) && sz == 16) goto none;
1802 if (o == GOF(VR28) && sz == 16) goto none;
1803 if (o == GOF(VR29) && sz == 16) goto none;
1804 if (o == GOF(VR30) && sz == 16) goto none;
1805 if (o == GOF(VR31) && sz == 16) goto none;
1807 /* Altivec admin related */
1808 if (o == GOF(VRSAVE) && is4) goto none;
1810 VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz);
1814 /* -------------------- arm -------------------- */
1816 # elif defined(VGA_arm)
1818 # define GOF(_fieldname) \
1819 (offsetof(VexGuestARMState,guest_##_fieldname))
1827 tl_assert(host_is_big_endian());
1829 /* Set default state to "does not intersect any int register". */
1830 VG_(memset)( iii, 0, sizeof(*iii) );
1832 VG_(printf)("get_IntRegInfo(arm):failing on (%d,%d)\n", o, sz);
1837 # error "FIXME: not implemented for this architecture"
1841 iii->n_offsets = -1;
1847 tl_assert(o >= 0 && 0 == (o % sizeof(UWord)));
1849 iii->offsets[0] = o;
1854 /* Does 'arr' describe an indexed guest state section containing host
1855 words, that we want to shadow? */
1857 static Bool is_integer_guest_reg_array ( IRRegArray* arr )
1859 /* --------------------- x86 --------------------- */
1860 # if defined(VGA_x86)
1861 /* The x87 tag array. */
1862 if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0])
1863 && arr->elemTy == Ity_I8 && arr->nElems == 8)
1865 /* The x87 register array. */
1866 if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0])
1867 && arr->elemTy == Ity_F64 && arr->nElems == 8)
1870 VG_(printf)("is_integer_guest_reg_array(x86): unhandled: ");
1875 /* -------------------- amd64 -------------------- */
1876 # elif defined(VGA_amd64)
1877 /* The x87 tag array. */
1878 if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0])
1879 && arr->elemTy == Ity_I8 && arr->nElems == 8)
1881 /* The x87 register array. */
1882 if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0])
1883 && arr->elemTy == Ity_F64 && arr->nElems == 8)
1886 VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: ");
1891 /* -------------------- ppc32 -------------------- */
1892 # elif defined(VGA_ppc32)
1893 /* The redir stack. */
1894 if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0])
1895 && arr->elemTy == Ity_I32
1896 && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE)
1899 VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: ");
1904 /* -------------------- ppc64 -------------------- */
1905 # elif defined(VGA_ppc64)
1906 /* The redir stack. */
1907 if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0])
1908 && arr->elemTy == Ity_I64
1909 && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE)
1912 VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: ");
1917 /* -------------------- arm -------------------- */
1918 # elif defined(VGA_arm)
1919 /* There are no rotating register sections on ARM. */
1920 VG_(printf)("is_integer_guest_reg_array(arm): unhandled: ");
1926 # error "FIXME: not implemented for this architecture"
1931 // END move this uglyness to pc_machine.c
1933 /* returns True iff given slice exactly matches an int reg. Merely
1934 a convenience wrapper around get_IntRegInfo. */
1935 static Bool is_integer_guest_reg ( Int offset, Int szB )
1938 get_IntRegInfo( &iii, offset, szB );
1939 tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
1940 return iii.n_offsets == -1;
1943 /* these assume guest and host have the same endianness and
1944 word size (probably). */
1945 static UWord get_guest_intreg ( ThreadId tid, Int shadowNo,
1946 PtrdiffT offset, SizeT size )
1948 UChar tmp[ 2 + sizeof(UWord) ];
1949 tl_assert(size == sizeof(UWord));
1950 tl_assert(0 == (offset % sizeof(UWord)));
1951 VG_(memset)(tmp, 0, sizeof(tmp));
1953 tmp[ sizeof(tmp)-1 ] = 0x27;
1954 VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size);
1955 tl_assert(tmp[0] == 0x31);
1956 tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27);
1957 return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */
1959 static void put_guest_intreg ( ThreadId tid, Int shadowNo,
1960 PtrdiffT offset, SizeT size, UWord w )
1962 tl_assert(size == sizeof(UWord));
1963 tl_assert(0 == (offset % sizeof(UWord)));
1964 VG_(set_shadow_regs_area)(tid, shadowNo, offset, size,
1968 /* Initialise the integer shadow registers to UNKNOWN. This is a bit
1969 of a nasty kludge, but it does mean we don't need to know which
1970 registers we really need to initialise -- simply assume that all
1971 integer registers will be naturally aligned w.r.t. the start of the
1972 guest state, and fill in all possible entries. */
1973 static void init_shadow_registers ( ThreadId tid )
1975 Int i, wordSzB = sizeof(UWord);
1976 for (i = 0; i < PC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) {
1977 put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN );
1981 static void post_reg_write_nonptr ( ThreadId tid, PtrdiffT offset, SizeT size )
1983 // syscall_return: Default is non-pointer. If it really is a pointer
1984 // (eg. for mmap()), SK_(post_syscall) sets it again afterwards.
1986 // clientreq_return: All the global client requests return non-pointers
1987 // (except possibly CLIENT_CALL[0123], but they're handled by
1988 // post_reg_write_clientcall, not here).
1990 if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1991 put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR );
1994 if (size == 1 || size == 2) {
1995 /* can't possibly be an integer guest reg. Ignore. */
1998 // DDD: on Darwin, this assertion fails because we currently do a
1999 // 'post_reg_write' on the 'guest_CC_DEP1' pseudo-register.
2000 // JRS 2009July13: we should change is_integer_guest_reg()
2001 // to accept guest_CC_DEP* and guest_CC_NDEP
2002 // as legitimate pointer-holding registers
2005 // VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR );
2008 static void post_reg_write_nonptr_or_unknown ( ThreadId tid,
2009 PtrdiffT offset, SizeT size )
2011 // deliver_signal: called from two places; one sets the reg to zero, the
2012 // other sets the stack pointer.
2014 if (is_integer_guest_reg( (Int)offset, (Int)size )) {
2016 tid, 1/*shadowno*/, offset, size,
2017 (UWord)nonptr_or_unknown(
2018 get_guest_intreg( tid, 0/*shadowno*/,
2025 void h_post_reg_write_demux ( CorePart part, ThreadId tid,
2026 PtrdiffT guest_state_offset, SizeT size)
2029 VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
2030 (Int)tid, (Int)part,
2031 guest_state_offset, size);
2033 case Vg_CoreStartup:
2034 /* This is a bit of a kludge since for any Vg_CoreStartup
2035 event we overwrite the entire shadow register set. But
2036 that's ok - we're only called once with
2037 part==Vg_CoreStartup event, and in that case the supplied
2038 offset & size cover the entire guest state anyway. */
2039 init_shadow_registers(tid);
2041 case Vg_CoreSysCall:
2042 if (0) VG_(printf)("ZZZZZZZ p_r_w -> NONPTR\n");
2043 post_reg_write_nonptr( tid, guest_state_offset, size );
2045 case Vg_CoreClientReq:
2046 post_reg_write_nonptr( tid, guest_state_offset, size );
2049 post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size );
2056 void h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
2057 SizeT size, Addr f )
2061 // Having to do this is a bit nasty...
2062 if (f == (Addr)h_replace_malloc
2063 || f == (Addr)h_replace___builtin_new
2064 || f == (Addr)h_replace___builtin_vec_new
2065 || f == (Addr)h_replace_calloc
2066 || f == (Addr)h_replace_memalign
2067 || f == (Addr)h_replace_realloc)
2069 // We remembered the last added segment; make sure it's the right one.
2070 /* What's going on: at this point, the scheduler has just called
2071 'f' -- one of our malloc replacement functions -- and it has
2072 returned. The return value has been written to the guest
2073 state of thread 'tid', offset 'guest_state_offset' length
2074 'size'. We need to look at that return value and set the
2075 shadow return value accordingly. The shadow return value
2076 required is handed to us "under the counter" through the
2077 global variable 'last_seg_added'. This is all very ugly, not
2078 to mention, non-thread-safe should V ever become
2080 /* assert the place where the return value is is a legit int reg */
2081 tl_assert(is_integer_guest_reg(guest_state_offset, size));
2082 /* Now we need to look at the returned value, to see whether the
2083 malloc succeeded or not. */
2084 p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size);
2085 if ((UWord)NULL == p) {
2086 // if alloc failed, eg. realloc on bogus pointer
2087 put_guest_intreg(tid, 1/*first-shadow*/,
2088 guest_state_offset, size, (UWord)NONPTR );
2090 // alloc didn't fail. Check we have the correct segment.
2091 tl_assert(p == last_seg_added->addr);
2092 put_guest_intreg(tid, 1/*first-shadow*/,
2093 guest_state_offset, size, (UWord)last_seg_added );
2096 else if (f == (Addr)h_replace_free
2097 || f == (Addr)h_replace___builtin_delete
2098 || f == (Addr)h_replace___builtin_vec_delete
2099 // || f == (Addr)VG_(cli_block_size)
2100 || f == (Addr)VG_(message))
2102 // Probably best to set the (non-existent!) return value to
2104 tl_assert(is_integer_guest_reg(guest_state_offset, size));
2105 put_guest_intreg(tid, 1/*first-shadow*/,
2106 guest_state_offset, size, (UWord)NONPTR );
2109 // Anything else, probably best to set return value to non-pointer.
2110 //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN);
2112 VG_(printf)("f = %#lx\n", f);
2113 VG_(get_fnname)(f, fbuf, 100);
2114 VG_(printf)("name = %s\n", fbuf);
2115 VG_(tool_panic)("argh: clientcall");
2120 //zz /*--------------------------------------------------------------------*/
2121 //zz /*--- Sanity checking ---*/
2122 //zz /*--------------------------------------------------------------------*/
2124 //zz /* Check that nobody has spuriously claimed that the first or last 16
2125 //zz pages (64 KB) of address space have become accessible. Failure of
2126 //zz the following do not per se indicate an internal consistency
2127 //zz problem, but they are so likely to that we really want to know
2128 //zz about it if so. */
2129 //zz Bool pc_replace_cheap_sanity_check) ( void )
2131 //zz if (IS_DISTINGUISHED_SM(primary_map[0])
2132 //zz /* kludge: kernel drops a page up at top of address range for
2133 //zz magic "optimized syscalls", so we can no longer check the
2134 //zz highest page */
2135 //zz /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
2142 //zz Bool SK_(expensive_sanity_check) ( void )
2146 //zz /* Make sure nobody changed the distinguished secondary. */
2147 //zz for (i = 0; i < SEC_MAP_WORDS; i++)
2148 //zz if (distinguished_secondary_map.vseg[i] != UNKNOWN)
2155 /*--------------------------------------------------------------------*/
2156 /*--- System calls ---*/
2157 /*--------------------------------------------------------------------*/
2159 void h_pre_syscall ( ThreadId tid, UInt sysno,
2160 UWord* args, UInt nArgs )
2162 /* we don't do anything at the pre-syscall point */
2165 /* The post-syscall table is a table of pairs (number, flag).
2167 'flag' is only ever zero or one. If it is zero, it indicates that
2168 default handling for that syscall is required -- namely that the
2169 syscall is deemed to return NONPTR. This is the case for the vast
2170 majority of syscalls. If it is one then some special
2171 syscall-specific handling is is required. No further details of it
2172 are stored in the table.
2174 On Linux and Darwin, 'number' is a __NR_xxx constant.
2176 On AIX5, 'number' is an Int*, which points to the Int variable
2177 holding the currently assigned number for this syscall.
2179 When querying the table, we compare the supplied syscall number
2180 with the 'number' field (directly on Linux and Darwin, after
2181 dereferencing on AIX5), to find the relevant entry. This requires a
2182 linear search of the table. To stop the costs getting too high, the
2183 table is incrementally rearranged after each search, to move commonly
2184 requested items a bit closer to the front.
2186 The table is built once, the first time it is used. After that we
2187 merely query it (and reorder the entries as a result). */
2189 static XArray* /* of UWordPair */ post_syscall_table = NULL;
2191 static void setup_post_syscall_table ( void )
2193 tl_assert(!post_syscall_table);
2194 post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1",
2195 VG_(free), sizeof(UWordPair) );
2196 tl_assert(post_syscall_table);
2198 /* --------------- LINUX --------------- */
2200 # if defined(VGO_linux)
2202 # define ADD(_flag, _syscallname) \
2203 do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2204 VG_(addToXA)( post_syscall_table, &p ); \
2207 /* These ones definitely don't return pointers. They're not
2208 particularly grammatical, either. */
2210 # if defined(__NR__llseek)
2211 ADD(0, __NR__llseek);
2213 ADD(0, __NR__sysctl);
2214 # if defined(__NR__newselect)
2215 ADD(0, __NR__newselect);
2217 # if defined(__NR_accept)
2218 ADD(0, __NR_accept);
2220 ADD(0, __NR_access);
2222 # if defined(__NR_bind)
2225 # if defined(__NR_chdir)
2230 # if defined(__NR_chown32)
2231 ADD(0, __NR_chown32);
2233 ADD(0, __NR_clock_getres);
2234 ADD(0, __NR_clock_gettime);
2237 # if defined(__NR_connect)
2238 ADD(0, __NR_connect);
2243 ADD(0, __NR_epoll_create);
2244 # if defined(__NR_epoll_create1)
2245 ADD(0, __NR_epoll_create1);
2247 ADD(0, __NR_epoll_ctl);
2248 # if defined(__NR_epoll_pwait)
2249 ADD(0, __NR_epoll_pwait);
2251 ADD(0, __NR_epoll_wait);
2252 ADD(0, __NR_execve); /* presumably we see this because the call failed? */
2253 ADD(0, __NR_exit); /* hmm, why are we still alive? */
2254 ADD(0, __NR_exit_group);
2255 ADD(0, __NR_fadvise64);
2256 ADD(0, __NR_fallocate);
2257 ADD(0, __NR_fchmod);
2258 ADD(0, __NR_fchown);
2259 # if defined(__NR_fchown32)
2260 ADD(0, __NR_fchown32);
2263 # if defined(__NR_fcntl64)
2264 ADD(0, __NR_fcntl64);
2266 ADD(0, __NR_fdatasync);
2269 # if defined(__NR_fstat64)
2270 ADD(0, __NR_fstat64);
2272 ADD(0, __NR_fstatfs);
2273 # if defined(__NR_fstatfs64)
2274 ADD(0, __NR_fstatfs64);
2277 ADD(0, __NR_ftruncate);
2278 # if defined(__NR_ftruncate64)
2279 ADD(0, __NR_ftruncate64);
2282 ADD(0, __NR_getcwd);
2283 ADD(0, __NR_getdents); // something to do with teeth
2284 ADD(0, __NR_getdents64);
2285 ADD(0, __NR_getegid);
2286 # if defined(__NR_getegid32)
2287 ADD(0, __NR_getegid32);
2289 ADD(0, __NR_geteuid);
2290 # if defined(__NR_geteuid32)
2291 ADD(0, __NR_geteuid32);
2293 ADD(0, __NR_getgid);
2294 # if defined(__NR_getgid32)
2295 ADD(0, __NR_getgid32);
2297 ADD(0, __NR_getgroups);
2298 # if defined(__NR_getgroups32)
2299 ADD(0, __NR_getgroups32);
2301 ADD(0, __NR_getitimer);
2302 # if defined(__NR_getpeername)
2303 ADD(0, __NR_getpeername);
2305 ADD(0, __NR_getpid);
2306 ADD(0, __NR_getpgrp);
2307 ADD(0, __NR_getppid);
2308 ADD(0, __NR_getpriority);
2309 ADD(0, __NR_getresgid);
2310 # if defined(__NR_getresgid32)
2311 ADD(0, __NR_getresgid32);
2313 ADD(0, __NR_getresuid);
2314 # if defined(__NR_getresuid32)
2315 ADD(0, __NR_getresuid32);
2317 ADD(0, __NR_getrlimit);
2318 ADD(0, __NR_getrusage);
2319 ADD(0, __NR_getsid);
2320 # if defined(__NR_getsockname)
2321 ADD(0, __NR_getsockname);
2323 # if defined(__NR_getsockopt)
2324 ADD(0, __NR_getsockopt);
2326 ADD(0, __NR_gettid);
2327 ADD(0, __NR_gettimeofday);
2328 ADD(0, __NR_getuid);
2329 # if defined(__NR_getuid32)
2330 ADD(0, __NR_getuid32);
2332 ADD(0, __NR_getxattr);
2333 ADD(0, __NR_inotify_add_watch);
2334 ADD(0, __NR_inotify_init);
2335 # if defined(__NR_inotify_init1)
2336 ADD(0, __NR_inotify_init1);
2338 ADD(0, __NR_inotify_rm_watch);
2339 ADD(0, __NR_ioctl); // ioctl -- assuming no pointers returned
2340 ADD(0, __NR_ioprio_get);
2343 # if defined(__NR_listen)
2344 ADD(0, __NR_listen);
2348 # if defined(__NR_lstat64)
2349 ADD(0, __NR_lstat64);
2351 ADD(0, __NR_madvise);
2354 ADD(0, __NR_mlockall);
2355 ADD(0, __NR_mprotect);
2356 ADD(0, __NR_munmap); // die_mem_munmap already called, segment remove);
2357 ADD(0, __NR_nanosleep);
2359 ADD(0, __NR_personality);
2361 # if defined(__NR_pipe2)
2366 ADD(0, __NR_pread64);
2367 ADD(0, __NR_pwrite64);
2369 ADD(0, __NR_readlink);
2371 # if defined(__NR_recvfrom)
2372 ADD(0, __NR_recvfrom);
2374 # if defined(__NR_recvmsg)
2375 ADD(0, __NR_recvmsg);
2377 ADD(0, __NR_rename);
2379 ADD(0, __NR_rt_sigaction);
2380 ADD(0, __NR_rt_sigprocmask);
2381 ADD(0, __NR_rt_sigreturn); /* not sure if we should see this or not */
2382 ADD(0, __NR_rt_sigsuspend);
2383 ADD(0, __NR_rt_sigtimedwait);
2384 ADD(0, __NR_sched_get_priority_max);
2385 ADD(0, __NR_sched_get_priority_min);
2386 ADD(0, __NR_sched_getaffinity);
2387 ADD(0, __NR_sched_getparam);
2388 ADD(0, __NR_sched_getscheduler);
2389 ADD(0, __NR_sched_setaffinity);
2390 ADD(0, __NR_sched_setscheduler);
2391 ADD(0, __NR_sched_yield);
2392 ADD(0, __NR_select);
2393 # if defined(__NR_semctl)
2394 ADD(0, __NR_semctl);
2396 # if defined(__NR_semget)
2397 ADD(0, __NR_semget);
2399 # if defined(__NR_semop)
2402 # if defined(__NR_sendto)
2403 ADD(0, __NR_sendto);
2405 # if defined(__NR_sendmsg)
2406 ADD(0, __NR_sendmsg);
2408 ADD(0, __NR_set_robust_list);
2409 # if defined(__NR_set_thread_area)
2410 ADD(0, __NR_set_thread_area);
2412 ADD(0, __NR_set_tid_address);
2413 ADD(0, __NR_setfsgid);
2414 ADD(0, __NR_setfsuid);
2415 ADD(0, __NR_setgid);
2416 ADD(0, __NR_setitimer);
2417 ADD(0, __NR_setpgid);
2418 ADD(0, __NR_setpriority);
2419 ADD(0, __NR_setregid);
2420 ADD(0, __NR_setresgid);
2421 ADD(0, __NR_setresuid);
2422 ADD(0, __NR_setreuid);
2423 ADD(0, __NR_setrlimit);
2424 ADD(0, __NR_setsid);
2425 # if defined(__NR_setsockopt)
2426 ADD(0, __NR_setsockopt);
2428 ADD(0, __NR_setuid);
2429 # if defined(__NR_shmctl)
2430 ADD(0, __NR_shmctl);
2433 # if defined(__NR_shutdown)
2434 ADD(0, __NR_shutdown);
2436 ADD(0, __NR_sigaltstack);
2437 # if defined(__NR_socket)
2438 ADD(0, __NR_socket);
2440 # if defined(__NR_socketcall)
2441 ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */
2443 # if defined(__NR_socketpair)
2444 ADD(0, __NR_socketpair);
2446 # if defined(__NR_statfs64)
2447 ADD(0, __NR_statfs64);
2449 # if defined(__NR_sigreturn)
2450 ADD(0, __NR_sigreturn); /* not sure if we should see this or not */
2452 # if defined(__NR_stat64)
2453 ADD(0, __NR_stat64);
2456 ADD(0, __NR_statfs);
2457 ADD(0, __NR_symlink);
2458 ADD(0, __NR_sysinfo);
2459 ADD(0, __NR_tgkill);
2462 ADD(0, __NR_truncate);
2463 # if defined(__NR_truncate64)
2464 ADD(0, __NR_truncate64);
2466 # if defined(__NR_ugetrlimit)
2467 ADD(0, __NR_ugetrlimit);
2471 ADD(0, __NR_unlink);
2474 # if defined(__NR_waitpid)
2475 ADD(0, __NR_waitpid);
2479 ADD(0, __NR_writev);
2481 /* Whereas the following need special treatment */
2482 # if defined(__NR_arch_prctl)
2483 ADD(1, __NR_arch_prctl);
2487 # if defined(__NR_mmap2)
2490 # if defined(__NR_shmat)
2493 # if defined(__NR_shmget)
2494 ADD(1, __NR_shmget);
2496 # if defined(__NR_ipc) && defined(VKI_SHMAT)
2497 ADD(1, __NR_ipc); /* ppc{32,64}-linux horrors */
2500 /* --------------- AIX5 --------------- */
2502 # elif defined(VGO_aix5)
2504 # define ADD(_flag, _syscallname) \
2507 if ((_syscallname) != __NR_AIX5_UNKNOWN) { \
2508 p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \
2509 VG_(addToXA)( post_syscall_table, &p ); \
2513 /* Just a minimal set of handlers, enough to make
2514 a 32- and 64-bit hello-world program run. */
2515 ADD(1, __NR_AIX5___loadx); /* not sure what to do here */
2516 ADD(0, __NR_AIX5__exit);
2517 ADD(0, __NR_AIX5_access);
2518 ADD(0, __NR_AIX5_getgidx);
2519 ADD(0, __NR_AIX5_getuidx);
2520 ADD(0, __NR_AIX5_kfcntl);
2521 ADD(0, __NR_AIX5_kioctl);
2522 ADD(1, __NR_AIX5_kload); /* not sure what to do here */
2523 ADD(0, __NR_AIX5_kwrite);
2525 /* --------------- DARWIN ------------- */
2527 # elif defined(VGO_darwin)
2529 # define ADD(_flag, _syscallname) \
2530 do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2531 VG_(addToXA)( post_syscall_table, &p ); \
2534 // DDD: a desultory attempt thus far...
2536 // Unix/BSD syscalls.
2539 ADD(0, __NR_host_self_trap);
2540 ADD(0, __NR_mach_msg_trap);
2541 ADD(0, __NR_mach_reply_port);
2542 ADD(0, __NR_task_self_trap);
2544 // Machine-dependent syscalls.
2545 ADD(0, __NR_thread_fast_set_cthread_self);
2547 /* ------------------------------------ */
2550 # error "Unsupported OS"
2557 void h_post_syscall ( ThreadId tid, UInt sysno,
2558 UWord* args, UInt nArgs, SysRes res )
2563 if (!post_syscall_table)
2564 setup_post_syscall_table();
2566 /* search for 'sysno' in the post_syscall_table */
2567 n = VG_(sizeXA)( post_syscall_table );
2568 for (i = 0; i < n; i++) {
2569 pair = VG_(indexXA)( post_syscall_table, i );
2570 # if defined(VGO_linux) || defined(VGO_darwin)
2571 if (pair->uw1 == (UWord)sysno)
2573 # elif defined(VGO_aix5)
2574 if (*(Int*)(pair->uw1) == (Int)sysno)
2577 # error "Unsupported OS"
2581 tl_assert(i >= 0 && i <= n);
2584 VG_(printf)("sysno == %s", VG_SYSNUM_STRING_EXTRA(sysno));
2585 VG_(tool_panic)("unhandled syscall");
2588 /* So we found the relevant entry. Move it one step
2589 forward so as to speed future accesses to it. */
2591 UWordPair tmp, *p, *q;
2592 p = VG_(indexXA)( post_syscall_table, i-1 );
2593 q = VG_(indexXA)( post_syscall_table, i-0 );
2600 /* Deal with the common case */
2601 pair = VG_(indexXA)( post_syscall_table, i );
2603 /* the common case */
2604 goto res_NONPTR_err_NONPTR;
2606 /* Special handling for all remaining cases */
2607 tl_assert(pair->uw2 == 1);
2609 # if defined(__NR_arch_prctl)
2610 if (sysno == __NR_arch_prctl) {
2611 /* This is nasty. On amd64-linux, arch_prctl may write a
2612 value to guest_FS_ZERO, and we need to shadow that value.
2613 Hence apply nonptr_or_unknown to it here, after the
2614 syscall completes. */
2615 post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO,
2617 goto res_NONPTR_err_NONPTR;
2621 # if defined(__NR_brk)
2622 // With brk(), result (of kernel syscall, not glibc wrapper) is a heap
2623 // pointer. Make the shadow UNKNOWN.
2624 if (sysno == __NR_brk)
2625 goto res_UNKNOWN_err_NONPTR;
2628 // With mmap, new_mem_mmap() has already been called and added the
2629 // segment (we did it there because we had the result address and size
2630 // handy). So just set the return value shadow.
2631 if (sysno == __NR_mmap
2632 # if defined(__NR_mmap2)
2633 || sysno == __NR_mmap2
2635 # if defined(__NR_AIX5___loadx)
2636 || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN)
2638 # if defined(__NR_AIX5_kload)
2639 || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN)
2642 if (sr_isError(res)) {
2643 // mmap() had an error, return value is a small negative integer
2644 goto res_NONPTR_err_NONPTR;
2646 goto res_UNKNOWN_err_NONPTR;
2651 // shmat uses the same scheme. We will just have had a
2652 // notification via new_mem_mmap. Just set the return value shadow.
2653 # if defined(__NR_shmat)
2654 if (sysno == __NR_shmat) {
2655 if (sr_isError(res)) {
2656 goto res_NONPTR_err_NONPTR;
2658 goto res_UNKNOWN_err_NONPTR;
2663 # if defined(__NR_shmget)
2664 if (sysno == __NR_shmget)
2665 // FIXME: is this correct?
2666 goto res_UNKNOWN_err_NONPTR;
2669 # if defined(__NR_ipc) && defined(VKI_SHMAT)
2670 /* perhaps this should be further conditionalised with
2671 && (defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
2672 Note, this just copies the behaviour of __NR_shmget above.
2674 JRS 2009 June 02: it seems that the return value from
2675 sys_ipc(VKI_SHMAT, ...) doesn't have much relationship to the
2676 result returned by the originating user-level shmat call. It's
2677 different (and much lower) by a large but integral number of
2678 pages. I don't have time to chase this right now. Observed on
2679 ppc{32,64}-linux. Result appears to be false errors from apps
2680 using shmat. Confusion though -- shouldn't be related to the
2681 actual numeric values returned by the syscall, though, should
2682 it? Confused. Maybe some bad interaction with a
2683 nonpointer-or-unknown heuristic? */
2684 if (sysno == __NR_ipc) {
2685 if (args[0] == VKI_SHMAT) {
2686 goto res_UNKNOWN_err_NONPTR;
2688 goto res_NONPTR_err_NONPTR;
2693 /* If we get here, it implies the corresponding entry in
2694 post_syscall_table has .w2 == 1, which in turn implies there
2695 should be special-case code for it above. */
2698 res_NONPTR_err_NONPTR:
2699 VG_(set_syscall_return_shadows)( tid, /* retval */ (UWord)NONPTR, 0,
2700 /* error */ (UWord)NONPTR, 0 );
2703 res_UNKNOWN_err_NONPTR:
2704 VG_(set_syscall_return_shadows)( tid, /* retval */ (UWord)UNKNOWN, 0,
2705 /* error */ (UWord)NONPTR, 0 );
2710 /*--------------------------------------------------------------------*/
2711 /*--- Functions called from generated code ---*/
2712 /*--------------------------------------------------------------------*/
2715 static void checkSeg ( Seg vseg ) {
2716 tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM
2717 || Seg__plausible(vseg) );
2721 // XXX: could be more sophisticated -- actually track the lowest/highest
2722 // valid address used by the program, and then return False for anything
2723 // below that (using a suitable safety margin). Also, nothing above
2724 // 0xc0000000 is valid [unless you've changed that in your kernel]
2725 static inline Bool looks_like_a_pointer(Addr a)
2727 # if defined(VGA_x86) || defined(VGA_ppc32)
2728 tl_assert(sizeof(UWord) == 4);
2729 return (a > 0x01000000UL && a < 0xFF000000UL);
2731 # elif defined(VGA_amd64) || defined(VGA_ppc64)
2732 tl_assert(sizeof(UWord) == 8);
2733 return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL);
2735 # elif defined(VGA_arm)
2736 /* Unfortunately arm-linux seems to load the exe at very low, at
2737 0x8000, so we have to assume any value above that is a pointer,
2738 which is pretty dismal. */
2739 tl_assert(sizeof(UWord) == 4);
2740 return (a >= 0x00008000UL && a < 0xFF000000UL);
2743 # error "Unsupported architecture"
2747 static inline VG_REGPARM(1)
2748 Seg* nonptr_or_unknown(UWord x)
2750 Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR;
2751 if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n",
2752 res==UNKNOWN ? "UUU" : "nnn", x);
2756 //zz static __attribute__((regparm(1)))
2757 //zz void print_BB_entry(UInt bb)
2759 //zz VG_(printf)("%u =\n", bb);
2762 //static ULong stats__tot_mem_refs = 0;
2763 //static ULong stats__refs_in_a_seg = 0;
2764 //static ULong stats__refs_lost_seg = 0;
2767 struct { ExeContext* ec; UWord count; }
2770 static OSet* lossage = NULL;
2772 //static void inc_lossage ( ExeContext* ec )
2774 // Lossage key, *res, *nyu;
2776 // key.count = 0; /* frivolous */
2777 // res = VG_(OSetGen_Lookup)(lossage, &key);
2779 // tl_assert(res->ec == ec);
2782 // nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage));
2786 // VG_(OSetGen_Insert)( lossage, nyu );
2790 static void init_lossage ( void )
2792 lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec),
2794 VG_(malloc), "pc.h_main.il.1",
2799 //static void show_lossage ( void )
2802 // VG_(OSetGen_ResetIter)( lossage );
2803 // while ( (elem = VG_(OSetGen_Next)(lossage)) ) {
2804 // if (elem->count < 10) continue;
2806 // //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1);
2807 // //buf[sizeof(buf)-1] = 0;
2808 // //VG_(printf)(" %,8lu %s\n", elem->count, buf);
2809 // VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count);
2810 // VG_(pp_ExeContext)(elem->ec);
2814 // This function is called *a lot*; inlining it sped up Konqueror by 20%.
2816 void check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg)
2820 if (h_clo_lossage_check) {
2822 stats__tot_mem_refs++;
2823 if (ISList__findI0( seglist, (Addr)m, &seg )) {
2824 /* m falls inside 'seg' (that is, we are making a memory
2825 reference inside 'seg'). Now, really mptr_vseg should be
2826 a tracked segment of some description. Badness is when
2827 mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point,
2828 since that means we've lost the type of it somehow: it
2829 shoud say that m points into a real segment (preferable
2830 'seg'), but it doesn't. */
2831 if (Seg__status_is_SegHeap(seg)) {
2832 stats__refs_in_a_seg++;
2833 if (UNKNOWN == mptr_vseg
2834 || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
2837 static UWord xx = 0;
2838 stats__refs_lost_seg++;
2839 ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
2842 VG_(message)(Vg_DebugMsg, "");
2843 VG_(message)(Vg_DebugMsg,
2844 "Lossage %s %#lx sz %lu inside block alloc'd",
2845 is_write ? "wr" : "rd", m, (UWord)sz);
2846 VG_(pp_ExeContext)(Seg__where(seg));
2849 Addr ip = VG_(get_IP)( VG_(get_running_tid)() );
2850 (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1);
2851 buf[sizeof(buf)-1] = 0;
2852 VG_(printf)("lossage at %p %s\n", ec, buf );
2857 } /* clo_lossage_check */
2861 checkSeg(mptr_vseg);
2864 if (UNKNOWN == mptr_vseg) {
2867 } else if (BOTTOM == mptr_vseg) {
2870 } else if (NONPTR == mptr_vseg) {
2871 h_record_heap_error( m, sz, mptr_vseg, is_write );
2874 // check all segment ranges in the circle
2875 // if none match, warn about 1st seg
2876 // else, check matching one isn't freed
2878 Seg* curr = mptr_vseg;
2881 // Accesses partly outside range are an error, unless it's an aligned
2882 // word-sized read, and --partial-loads-ok=yes. This is to cope with
2883 // gcc's/glibc's habits of doing word-sized accesses that read past
2884 // the ends of arrays/strings.
2885 // JRS 2008-sept-11: couldn't this be moved off the critical path?
2886 if (!is_write && sz == sizeof(UWord)
2887 && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
2893 if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi);
2894 is_ok = curr->addr <= m && mhi < curr->addr + curr->szB;
2896 // If it's an overrun/underrun of a freed block, don't give both
2897 // warnings, since the first one mentions that the block has been
2899 if ( ! is_ok || Seg__is_freed(curr) )
2900 h_record_heap_error( m, sz, mptr_vseg, is_write );
2904 // ------------------ Load handlers ------------------ //
2906 /* On 32 bit targets, we will use:
2907 check_load1 check_load2 check_load4_P
2908 check_load4 (for 32-bit FP reads)
2909 check_load8 (for 64-bit FP reads)
2910 check_load16 (for xmm/altivec reads)
2911 On 64 bit targets, we will use:
2912 check_load1 check_load2 check_load4 check_load8_P
2913 check_load8 (for 64-bit FP reads)
2914 check_load16 (for xmm/altivec reads)
2916 A "_P" handler reads a pointer from memory, and so returns a value
2917 to the generated code -- the pointer's shadow value. That implies
2918 that check_load4_P is only to be called on a 32 bit host and
2919 check_load8_P is only to be called on a 64 bit host. For all other
2920 cases no shadow value is returned; we merely check that the pointer
2921 (m) matches the block described by its shadow value (mptr_vseg).
2924 // This handles 128 bit loads on both 32 bit and 64 bit targets.
2925 static VG_REGPARM(2)
2926 void check_load16(Addr m, Seg* mptr_vseg)
2929 checkSeg(mptr_vseg);
2931 check_load_or_store(/*is_write*/False, m, 16, mptr_vseg);
2934 // This handles 64 bit FP-or-otherwise-nonpointer loads on both
2935 // 32 bit and 64 bit targets.
2936 static VG_REGPARM(2)
2937 void check_load8(Addr m, Seg* mptr_vseg)
2940 checkSeg(mptr_vseg);
2942 check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2945 // This handles 64 bit loads on 64 bit targets. It must
2946 // not be called on 32 bit targets.
2948 static VG_REGPARM(2)
2949 Seg* check_load8_P(Addr m, Seg* mptr_vseg)
2952 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2954 checkSeg(mptr_vseg);
2956 check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2957 if (VG_IS_8_ALIGNED(m)) {
2958 vseg = get_mem_vseg(m);
2960 vseg = nonptr_or_unknown( *(ULong*)m );
2965 // This handles 32 bit loads on 32 bit targets. It must
2966 // not be called on 64 bit targets.
2968 static VG_REGPARM(2)
2969 Seg* check_load4_P(Addr m, Seg* mptr_vseg)
2972 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2974 checkSeg(mptr_vseg);
2976 check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2977 if (VG_IS_4_ALIGNED(m)) {
2978 vseg = get_mem_vseg(m);
2980 vseg = nonptr_or_unknown( *(UInt*)m );
2985 // Used for both 32 bit and 64 bit targets.
2986 static VG_REGPARM(2)
2987 void check_load4(Addr m, Seg* mptr_vseg)
2990 checkSeg(mptr_vseg);
2992 check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2995 // Used for both 32 bit and 64 bit targets.
2996 static VG_REGPARM(2)
2997 void check_load2(Addr m, Seg* mptr_vseg)
3000 checkSeg(mptr_vseg);
3002 check_load_or_store(/*is_write*/False, m, 2, mptr_vseg);
3005 // Used for both 32 bit and 64 bit targets.
3006 static VG_REGPARM(2)
3007 void check_load1(Addr m, Seg* mptr_vseg)
3010 checkSeg(mptr_vseg);
3012 check_load_or_store(/*is_write*/False, m, 1, mptr_vseg);
3015 // ------------------ Store handlers ------------------ //
3017 /* On 32 bit targets, we will use:
3018 check_store1 check_store2 check_store4_P check_store4C_P
3019 check_store4 (for 32-bit nonpointer stores)
3020 check_store8_ms4B_ls4B (for 64-bit stores)
3021 check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores)
3023 On 64 bit targets, we will use:
3024 check_store1 check_store2 check_store4 check_store4C
3025 check_store8_P check_store_8C_P
3026 check_store8_all8B (for 64-bit nonpointer stores)
3027 check_store16_ms8B_ls8B (for xmm/altivec stores)
3029 A "_P" handler writes a pointer to memory, and so has an extra
3030 argument -- the pointer's shadow value. That implies that
3031 check_store4{,C}_P is only to be called on a 32 bit host and
3032 check_store8{,C}_P is only to be called on a 64 bit host. For all
3033 other cases, and for the misaligned _P cases, the strategy is to
3034 let the store go through, and then snoop around with
3035 nonptr_or_unknown to fix up the shadow values of any affected
3038 /* Helpers for store-conditionals. Ugly kludge :-(
3039 They all return 1 if the SC was successful and 0 if it failed. */
3040 static inline UWord do_store_conditional_32( Addr m/*dst*/, UInt t/*val*/ )
3042 # if defined(VGA_ppc32) || defined(VGA_ppc64)
3044 /* If this assertion fails, the underlying IR is (semantically) ill-formed
3045 as per the IR spec for IRStmt_Store. */
3046 tl_assert(VG_IS_4_ALIGNED(m));
3047 __asm__ __volatile__(
3048 "stwcx. %2,0,%1" "\n\t" /* data,0,addr */
3050 "srwi %0,%0,29" "\n\t" /* move relevant CR bit to LSB */
3051 : /*out*/"=b"(success)
3052 : /*in*/ "b"(m), "b"( (UWord)t )
3053 : /*trash*/ "memory", "cc"
3054 /* Note: srwi is OK even on 64-bit host because the we're
3055 after bit 29 (normal numbering) and we mask off all the
3056 other junk just below. */
3058 return success & (UWord)1;
3060 tl_assert(0); /* not implemented on other platforms */
3064 static inline UWord do_store_conditional_64( Addr m/*dst*/, ULong t/*val*/ )
3066 # if defined(VGA_ppc64)
3068 /* If this assertion fails, the underlying IR is (semantically) ill-formed
3069 as per the IR spec for IRStmt_Store. */
3070 tl_assert(VG_IS_8_ALIGNED(m));
3071 __asm__ __volatile__(
3072 "stdcx. %2,0,%1" "\n\t" /* data,0,addr */
3074 "srdi %0,%0,29" "\n\t" /* move relevant CR bit to LSB */
3075 : /*out*/"=b"(success)
3076 : /*in*/ "b"(m), "b"( (UWord)t )
3077 : /*trash*/ "memory", "cc"
3079 return success & (UWord)1;
3081 tl_assert(0); /* not implemented on other platforms */
3085 /* Apply nonptr_or_unknown to all the words intersecting
3087 static inline VG_REGPARM(2)
3088 void nonptr_or_unknown_range ( Addr a, SizeT len )
3090 const SizeT wszB = sizeof(UWord);
3091 Addr wfirst = VG_ROUNDDN(a, wszB);
3092 Addr wlast = VG_ROUNDDN(a+len-1, wszB);
3094 tl_assert(wfirst <= wlast);
3095 for (a2 = wfirst ; a2 <= wlast; a2 += wszB) {
3096 set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 ));
3100 // Write to shadow memory, for a 32-bit store. Must only
3101 // be used on 32-bit targets.
3102 static inline VG_REGPARM(2)
3103 void do_shadow_store4_P( Addr m, Seg* vseg )
3105 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3106 if (VG_IS_4_ALIGNED(m)) {
3107 set_mem_vseg( m, vseg );
3109 // straddling two words
3110 nonptr_or_unknown_range(m, 4);
3114 // Write to shadow memory, for a 64-bit store. Must only
3115 // be used on 64-bit targets.
3116 static inline VG_REGPARM(2)
3117 void do_shadow_store8_P( Addr m, Seg* vseg )
3119 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3120 if (VG_IS_8_ALIGNED(m)) {
3121 set_mem_vseg( m, vseg );
3123 // straddling two words
3124 nonptr_or_unknown_range(m, 8);
3128 // This handles 128 bit stores on 64 bit targets. The
3129 // store data is passed in 2 pieces, the most significant
3131 static VG_REGPARM(3)
3132 void check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg,
3133 UWord ms8B, UWord ls8B)
3135 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3137 checkSeg(mptr_vseg);
3139 check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
3140 // Actually *do* the STORE here
3141 if (host_is_little_endian()) {
3142 // FIXME: aren't we really concerned whether the guest
3143 // is little endian, not whether the host is?
3144 *(ULong*)(m + 0) = ls8B;
3145 *(ULong*)(m + 8) = ms8B;
3147 *(ULong*)(m + 0) = ms8B;
3148 *(ULong*)(m + 8) = ls8B;
3150 nonptr_or_unknown_range(m, 16);
3153 // This handles 128 bit stores on 64 bit targets. The
3154 // store data is passed in 2 pieces, the most significant
3156 static VG_REGPARM(3)
3157 void check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg,
3158 UWord ms4B, UWord w2,
3159 UWord w1, UWord ls4B)
3161 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3163 checkSeg(mptr_vseg);
3165 check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
3166 // Actually *do* the STORE here
3167 if (host_is_little_endian()) {
3168 // FIXME: aren't we really concerned whether the guest
3169 // is little endian, not whether the host is?
3170 *(UInt*)(m + 0) = ls4B;
3171 *(UInt*)(m + 4) = w1;
3172 *(UInt*)(m + 8) = w2;
3173 *(UInt*)(m + 12) = ms4B;
3175 *(UInt*)(m + 0) = ms4B;
3176 *(UInt*)(m + 4) = w2;
3177 *(UInt*)(m + 8) = w1;
3178 *(UInt*)(m + 12) = ls4B;
3180 nonptr_or_unknown_range(m, 16);
3183 // This handles 64 bit stores on 32 bit targets. The
3184 // store data is passed in 2 pieces, the most significant
3186 static VG_REGPARM(3)
3187 void check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg,
3188 UWord ms4B, UWord ls4B)
3190 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3192 checkSeg(mptr_vseg);
3194 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3195 // Actually *do* the STORE here
3196 if (host_is_little_endian()) {
3197 // FIXME: aren't we really concerned whether the guest
3198 // is little endian, not whether the host is?
3199 *(UInt*)(m + 0) = ls4B;
3200 *(UInt*)(m + 4) = ms4B;
3202 *(UInt*)(m + 0) = ms4B;
3203 *(UInt*)(m + 4) = ls4B;
3205 nonptr_or_unknown_range(m, 8);
3208 // This handles 64 bit non pointer stores on 64 bit targets.
3209 // It must not be called on 32 bit targets.
3210 static VG_REGPARM(3)
3211 void check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B)
3213 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3215 checkSeg(mptr_vseg);
3217 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3218 // Actually *do* the STORE here
3220 nonptr_or_unknown_range(m, 8);
3223 // This handles 64 bit stores on 64 bit targets. It must
3224 // not be called on 32 bit targets.
3225 static VG_REGPARM(3)
3226 void check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3228 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3231 checkSeg(mptr_vseg);
3233 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3234 // Actually *do* the STORE here
3236 do_shadow_store8_P( m, t_vseg );
3239 // This handles 64 bit store-conditionals on 64 bit targets. It must
3240 // not be called on 32 bit targets.
3241 static VG_REGPARM(3)
3242 UWord check_store8C_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3245 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3248 checkSeg(mptr_vseg);
3250 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3251 // Actually *do* the STORE here
3252 success = do_store_conditional_64( m, t );
3254 do_shadow_store8_P( m, t_vseg );
3258 // This handles 32 bit stores on 32 bit targets. It must
3259 // not be called on 64 bit targets.
3260 static VG_REGPARM(3)
3261 void check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3263 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3266 checkSeg(mptr_vseg);
3268 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3269 // Actually *do* the STORE here
3271 do_shadow_store4_P( m, t_vseg );
3274 // This handles 32 bit store-conditionals on 32 bit targets. It must
3275 // not be called on 64 bit targets.
3276 static VG_REGPARM(3)
3277 UWord check_store4C_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3280 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3283 checkSeg(mptr_vseg);
3285 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3286 // Actually *do* the STORE here
3287 success = do_store_conditional_32( m, t );
3289 do_shadow_store4_P( m, t_vseg );
3293 // Used for both 32 bit and 64 bit targets.
3294 static VG_REGPARM(3)
3295 void check_store4(Addr m, Seg* mptr_vseg, UWord t)
3298 checkSeg(mptr_vseg);
3300 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3301 // Actually *do* the STORE here (Nb: cast must be to 4-byte type!)
3303 nonptr_or_unknown_range(m, 4);
3306 // Used for 32-bit store-conditionals on 64 bit targets only. It must
3307 // not be called on 32 bit targets.
3308 static VG_REGPARM(3)
3309 UWord check_store4C(Addr m, Seg* mptr_vseg, UWord t)
3312 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3314 checkSeg(mptr_vseg);
3316 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3317 // Actually *do* the STORE here
3318 success = do_store_conditional_32( m, t );
3320 nonptr_or_unknown_range(m, 4);
3324 // Used for both 32 bit and 64 bit targets.
3325 static VG_REGPARM(3)
3326 void check_store2(Addr m, Seg* mptr_vseg, UWord t)
3329 checkSeg(mptr_vseg);
3331 check_load_or_store(/*is_write*/True, m, 2, mptr_vseg);
3332 // Actually *do* the STORE here (Nb: cast must be to 2-byte type!)
3334 nonptr_or_unknown_range(m, 2);
3337 // Used for both 32 bit and 64 bit targets.
3338 static VG_REGPARM(3)
3339 void check_store1(Addr m, Seg* mptr_vseg, UWord t)
3342 checkSeg(mptr_vseg);
3344 check_load_or_store(/*is_write*/True, m, 1, mptr_vseg);
3345 // Actually *do* the STORE here (Nb: cast must be to 1-byte type!)
3347 nonptr_or_unknown_range(m, 1);
3351 // Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM
3352 // be changed to NONPTR by a range check on the result.
3353 #define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \
3354 if (BOTTOM == seg1 || BOTTOM == seg2) { bt; \
3355 } else if (NONPTR == seg1) { if (NONPTR == seg2) { nn; } \
3356 else if (UNKNOWN == seg2) { nu; } \
3358 } else if (UNKNOWN == seg1) { if (NONPTR == seg2) { un; } \
3359 else if (UNKNOWN == seg2) { uu; } \
3361 } else { if (NONPTR == seg2) { pn; } \
3362 else if (UNKNOWN == seg2) { pu; } \
3366 #define BINERROR(opname) \
3367 h_record_arith_error(seg1, seg2, opname); \
3376 // p | p ? e (all results become n if they look like a non-pointer)
3378 static Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname)
3387 out = NONPTR, out = UNKNOWN, out = seg2,
3388 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3389 out = seg1, out = UNKNOWN, BINERROR(opname)
3391 return ( looks_like_a_pointer(result) ? out : NONPTR );
3394 static VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result)
3401 out = do_addW_result(seg1, seg2, result, "Add32/Add64");
3409 // - | n ? p (Nb: operation is seg1 - seg2)
3411 // n | n ? n+ (+) happens a lot due to "cmp", but result should never
3412 // ? | ? ? n/B be used, so give 'n'
3413 // p | p p? n*/B (*) and possibly link the segments
3415 static VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result)
3422 // Nb: when returning BOTTOM, don't let it go through the range-check;
3423 // a segment linking offset can easily look like a nonptr.
3426 out = NONPTR, out = UNKNOWN, out = NONPTR,
3427 out = UNKNOWN, out = UNKNOWN, return BOTTOM,
3428 out = seg1, out = seg1/*??*/, return BOTTOM
3431 // This is for the p-p segment-linking case
3433 while (end2->links != seg2) end2 = end2->links;
3434 end2->links = seg1->links;
3438 return ( looks_like_a_pointer(result) ? out : NONPTR );
3446 // p | p ? * (*) if p1==p2 then p else e (see comment)
3448 /* Seems to be OK to And two pointers:
3451 which possibly derives from
3452 if (ptr1 & ptr2) { A } else { B }
3453 not sure what that means
3455 static VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2,
3456 UWord result, UWord args_diff)
3459 if (0 == args_diff) {
3465 out = NONPTR, out = UNKNOWN, out = seg2,
3466 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3467 out = seg1, out = UNKNOWN, out = NONPTR
3468 /*BINERROR("And32/And64")*/
3471 out = ( looks_like_a_pointer(result) ? out : NONPTR );
3482 /* It's OK to Or two pointers together, but the result definitely
3483 isn't a pointer. Why would you want to do that? Because of this:
3484 char* p1 = malloc(..);
3485 char* p2 = malloc(..);
3487 if (p1 || p2) { .. }
3488 In this case gcc on x86/amd64 quite literally or-s the two pointers
3489 together and throws away the result, the purpose of which is merely
3490 to sets %eflags.Z/%rflags.Z. So we have to allow it.
3492 static VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result)
3497 out = NONPTR, out = UNKNOWN, out = seg2,
3498 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3499 out = seg1, out = UNKNOWN, out = NONPTR
3501 out = ( looks_like_a_pointer(result) ? out : NONPTR );
3510 static VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result)
3515 if (BOTTOM == seg1) return BOTTOM;
3519 // Pointers are rarely multiplied, but sometimes legitimately, eg. as hash
3520 // function inputs. But two pointers args --> error.
3521 // Pretend it always returns a nonptr. Maybe improve later.
3522 static VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2)
3528 if (is_known_segment(seg1) && is_known_segment(seg2))
3529 h_record_arith_error(seg1, seg2, "Mul32/Mul64");
3534 /*--------------------------------------------------------------------*/
3535 /*--- Instrumentation ---*/
3536 /*--------------------------------------------------------------------*/
3538 /* The h_ instrumenter that follows is complex, since it deals with
3539 shadow value computation.
3541 It also needs to generate instrumentation for the sg_ side of
3542 things. That's relatively straightforward. However, rather than
3543 confuse the code herein any further, we simply delegate the problem
3544 to sg_main.c, by using the four functions
3545 sg_instrument_{init,fini,IRStmt,final_jump}. These four completely
3546 abstractify the sg_ instrumentation. See comments in sg_main.c's
3547 instrumentation section for further details. */
3550 /* Carries info about a particular tmp. The tmp's number is not
3551 recorded, as this is implied by (equal to) its index in the tmpMap
3552 in PCEnv. The tmp's type is also not recorded, as this is present
3555 When .kind is NonShad, .shadow may give the identity of the temp
3556 currently holding the associated shadow value, or it may be
3557 IRTemp_INVALID if code to compute the shadow has not yet been
3560 When .kind is Shad tmp holds a shadow value, and so .shadow must be
3561 IRTemp_INVALID, since it is illogical for a shadow tmp itself to be
3565 enum { NonShad=1, Shad=2 }
3577 /* Carries around state during Ptrcheck instrumentation. */
3580 /* MODIFIED: the superblock being constructed. IRStmts are
3585 /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
3586 current kind and possibly shadow temps for each temp in the
3587 IRSB being constructed. Note that it does not contain the
3588 type of each tmp. If you want to know the type, look at the
3589 relevant entry in sb->tyenv. It follows that at all times
3590 during the instrumentation process, the valid indices for
3591 tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
3592 total number of NonShad and Shad temps allocated so far.
3594 The reason for this strange split (types in one place, all
3595 other info in another) is that we need the types to be
3596 attached to sb so as to make it possible to do
3597 "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
3598 instrumentation process.
3600 Note that only integer temps of the guest word size are
3601 shadowed, since it is impossible (or meaningless) to hold a
3602 pointer in any other type of temp. */
3603 XArray* /* of TempMapEnt */ qmpMap;
3605 /* READONLY: the host word type. Needed for constructing
3606 arguments of type 'HWord' to be passed to helper functions.
3607 Ity_I32 or Ity_I64 only. */
3610 /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
3613 /* READONLY: the guest state size, so we can generate shadow
3614 offsets correctly. */
3615 Int guest_state_sizeB;
3619 /* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
3620 demand), as they are encountered. This is for two reasons.
3622 (1) (less important reason): Many original tmps are unused due to
3623 initial IR optimisation, and we do not want to spaces in tables
3626 Shadow IRTemps are therefore allocated on demand. pce.tmpMap is a
3627 table indexed [0 .. n_types-1], which gives the current shadow for
3628 each original tmp, or INVALID_IRTEMP if none is so far assigned.
3629 It is necessary to support making multiple assignments to a shadow
3630 -- specifically, after testing a shadow for definedness, it needs
3631 to be made defined. But IR's SSA property disallows this.
3633 (2) (more important reason): Therefore, when a shadow needs to get
3634 a new value, a new temporary is created, the value is assigned to
3635 that, and the tmpMap is updated to reflect the new binding.
3637 A corollary is that if the tmpMap maps a given tmp to
3638 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
3639 there's a read-before-write error in the original tmps. The IR
3640 sanity checker should catch all such anomalies, however.
3643 /* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
3644 both the table in pce->sb and to our auxiliary mapping. Note that
3645 newTemp may cause pce->tmpMap to resize, hence previous results
3646 from VG_(indexXA)(pce->tmpMap) are invalidated. */
3647 static IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind )
3651 IRTemp tmp = newIRTemp(pce->sb->tyenv, ty);
3653 ent.shadow = IRTemp_INVALID;
3654 newIx = VG_(addToXA)( pce->qmpMap, &ent );
3655 tl_assert(newIx == (Word)tmp);
3659 /* Find the tmp currently shadowing the given original tmp. If none
3660 so far exists, allocate one. */
3661 static IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig )
3664 /* VG_(indexXA) range-checks 'orig', hence no need to check
3666 ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3667 tl_assert(ent->kind == NonShad);
3668 if (ent->shadow == IRTemp_INVALID) {
3669 IRTemp shadow = newTemp( pce, pce->gWordTy, Shad );
3670 /* newTemp may cause pce->tmpMap to resize, hence previous results
3671 from VG_(indexXA) are invalid. */
3672 ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3673 tl_assert(ent->kind == NonShad);
3674 tl_assert(ent->shadow == IRTemp_INVALID);
3675 ent->shadow = shadow;
3680 /* Allocate a new shadow for the given original tmp. This means any
3681 previous shadow is abandoned. This is needed because it is
3682 necessary to give a new value to a shadow once it has been tested
3683 for undefinedness, but unfortunately IR's SSA property disallows
3684 this. Instead we must abandon the old shadow, allocate a new one
3685 and use that instead.
3687 This is the same as findShadowTmp, except we don't bother to see
3688 if a shadow temp already existed -- we simply allocate a new one
3690 static IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig )
3693 /* VG_(indexXA) range-checks 'orig', hence no need to check
3695 ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3696 tl_assert(ent->kind == NonShad);
3698 IRTemp shadow = newTemp( pce, pce->gWordTy, Shad );
3699 /* newTemp may cause pce->tmpMap to resize, hence previous results
3700 from VG_(indexXA) are invalid. */
3701 ent = (TempMapEnt*)VG_(indexXA)( pce->qmpMap, (Word)orig );
3702 tl_assert(ent->kind == NonShad);
3703 ent->shadow = shadow;
3711 /*------------------------------------------------------------*/
3712 /*--- IRAtoms -- a subset of IRExprs ---*/
3713 /*------------------------------------------------------------*/
3715 /* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
3716 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
3717 input, most of this code deals in atoms. Usefully, a value atom
3718 always has a V-value which is also an atom: constants are shadowed
3719 by constants, and temps are shadowed by the corresponding shadow
3722 typedef IRExpr IRAtom;
3724 //zz /* (used for sanity checks only): is this an atom which looks
3725 //zz like it's from original code? */
3726 //zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 )
3728 //zz if (a1->tag == Iex_Const)
3730 //zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps)
3735 //zz /* (used for sanity checks only): is this an atom which looks
3736 //zz like it's from shadow code? */
3737 //zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 )
3739 //zz if (a1->tag == Iex_Const)
3741 //zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps)
3746 //zz /* (used for sanity checks only): check that both args are atoms and
3747 //zz are identically-kinded. */
3748 //zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
3750 //zz if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
3752 //zz if (a1->tag == Iex_Const && a2->tag == Iex_Const)
3758 /*------------------------------------------------------------*/
3759 /*--- Constructing IR fragments ---*/
3760 /*------------------------------------------------------------*/
3762 /* add stmt to a bb */
3763 static inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
3765 VG_(printf)(" %c: ", cat);
3769 addStmtToIRSB(pce->sb, st);
3772 /* assign value to tmp */
3774 void assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) {
3775 stmt(cat, pce, IRStmt_WrTmp(tmp,expr));
3778 /* build various kinds of expressions */
3779 #define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
3780 #define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
3781 #define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
3782 #define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
3783 #define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
3784 #define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
3785 #define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
3786 #define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
3788 /* Bind the given expression to a new temporary, and return the
3789 temporary. This effectively converts an arbitrary expression into
3792 'ty' is the type of 'e' and hence the type that the new temporary
3793 needs to be. But passing it is redundant, since we can deduce the
3794 type merely by inspecting 'e'. So at least that fact to assert
3795 that the two types agree. */
3796 static IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) {
3798 IRType tyE = typeOfIRExpr(pce->sb->tyenv, e);
3799 tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
3800 t = newTemp(pce, ty, Shad);
3801 assign(cat, pce, t, e);
3807 //-----------------------------------------------------------------------
3808 // Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows.
3810 // Range check (NONPTR/seg):
3811 // - after modifying a word-sized value in/into a TempReg:
3812 // - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L
3815 // Range check (NONPTR/UNKNOWN):
3816 // - when introducing a new word-sized value into a TempReg:
3819 // - when copying a word-sized value which lacks a corresponding segment
3823 // - when a sub-word of a word (or two) is updated:
3825 // - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB]
3827 // - straddled STL (2 range checks)
3828 // - straddled STW (2 range checks)
3829 // - unstraddled STW
3833 // - when copying word-sized values:
3834 // - MOVL t1, t2 (--optimise=no only)
3837 // - unstraddled LDL, unstraddled STL
3839 // - when barely changing
3840 // - INC[LWB]/DEC[LWB]
3843 // - after copying a sub-word value into a TempReg:
3846 // - unstraddled LDW
3851 // - after copying an obvious non-ptr into a TempReg:
3856 // - after copying an obvious non-ptr into a memory word:
3863 // - CALLM_[SE], PUSHL, CALLM, CLEAR
3864 // - FPU, FPU_R (and similar MMX/SSE ones)
3870 /* Call h_fn (name h_nm) with the given arg, and return a new IRTemp
3871 holding the result. The arg must be a word-typed atom. Callee
3872 must be a VG_REGPARM(1) function. */
3873 __attribute__((noinline))
3874 static IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3879 tl_assert(isIRAtom(a1));
3880 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3881 res = newTemp(pce, pce->gWordTy, Shad);
3882 di = unsafeIRDirty_1_N( res, 1/*regparms*/,
3883 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3884 mkIRExprVec_1( a1 ) );
3885 stmt( 'I', pce, IRStmt_Dirty(di) );
3889 /* Two-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(2)
3891 static IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3892 IRExpr* a1, IRExpr* a2 )
3896 tl_assert(isIRAtom(a1));
3897 tl_assert(isIRAtom(a2));
3898 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3899 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3900 res = newTemp(pce, pce->gWordTy, Shad);
3901 di = unsafeIRDirty_1_N( res, 2/*regparms*/,
3902 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3903 mkIRExprVec_2( a1, a2 ) );
3904 stmt( 'I', pce, IRStmt_Dirty(di) );
3908 /* Three-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3)
3910 static IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3911 IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3915 tl_assert(isIRAtom(a1));
3916 tl_assert(isIRAtom(a2));
3917 tl_assert(isIRAtom(a3));
3918 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3919 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3920 tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3921 res = newTemp(pce, pce->gWordTy, Shad);
3922 di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3923 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3924 mkIRExprVec_3( a1, a2, a3 ) );
3925 stmt( 'I', pce, IRStmt_Dirty(di) );
3929 /* Four-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3)
3931 static IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3932 IRExpr* a1, IRExpr* a2,
3933 IRExpr* a3, IRExpr* a4 )
3937 tl_assert(isIRAtom(a1));
3938 tl_assert(isIRAtom(a2));
3939 tl_assert(isIRAtom(a3));
3940 tl_assert(isIRAtom(a4));
3941 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3942 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3943 tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3944 tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy);
3945 res = newTemp(pce, pce->gWordTy, Shad);
3946 di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3947 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3948 mkIRExprVec_4( a1, a2, a3, a4 ) );
3949 stmt( 'I', pce, IRStmt_Dirty(di) );
3953 /* Version of gen_dirty_W_WW with no return value. Callee must be a
3954 VG_REGPARM(2) function. If guard is non-NULL then it is used to
3955 conditionalise the call. */
3956 static void gen_dirty_v_WW ( PCEnv* pce, IRExpr* guard,
3957 void* h_fn, HChar* h_nm,
3958 IRExpr* a1, IRExpr* a2 )
3961 tl_assert(isIRAtom(a1));
3962 tl_assert(isIRAtom(a2));
3963 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3964 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3965 di = unsafeIRDirty_0_N( 2/*regparms*/,
3966 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3967 mkIRExprVec_2( a1, a2 ) );
3970 stmt( 'I', pce, IRStmt_Dirty(di) );
3973 /* Version of gen_dirty_W_WWW with no return value. Callee must be a
3974 VG_REGPARM(3) function.*/
3975 static void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3976 IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3979 tl_assert(isIRAtom(a1));
3980 tl_assert(isIRAtom(a2));
3981 tl_assert(isIRAtom(a3));
3982 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
3983 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
3984 tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
3985 di = unsafeIRDirty_0_N( 3/*regparms*/,
3986 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3987 mkIRExprVec_3( a1, a2, a3 ) );
3988 stmt( 'I', pce, IRStmt_Dirty(di) );
3991 /* Version of gen_dirty_v_WWW for 4 arguments. Callee must be a
3992 VG_REGPARM(3) function.*/
3993 static void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3994 IRExpr* a1, IRExpr* a2,
3995 IRExpr* a3, IRExpr* a4 )
3998 tl_assert(isIRAtom(a1));
3999 tl_assert(isIRAtom(a2));
4000 tl_assert(isIRAtom(a3));
4001 tl_assert(isIRAtom(a4));
4002 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
4003 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
4004 tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
4005 tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy);
4006 di = unsafeIRDirty_0_N( 3/*regparms*/,
4007 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
4008 mkIRExprVec_4( a1, a2, a3, a4 ) );
4009 stmt( 'I', pce, IRStmt_Dirty(di) );
4012 /* Version of gen_dirty_v_WWW for 6 arguments. Callee must be a
4013 VG_REGPARM(3) function.*/
4014 static void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm,
4015 IRExpr* a1, IRExpr* a2, IRExpr* a3,
4016 IRExpr* a4, IRExpr* a5, IRExpr* a6 )
4019 tl_assert(isIRAtom(a1));
4020 tl_assert(isIRAtom(a2));
4021 tl_assert(isIRAtom(a3));
4022 tl_assert(isIRAtom(a4));
4023 tl_assert(isIRAtom(a5));
4024 tl_assert(isIRAtom(a6));
4025 tl_assert(typeOfIRExpr(pce->sb->tyenv, a1) == pce->gWordTy);
4026 tl_assert(typeOfIRExpr(pce->sb->tyenv, a2) == pce->gWordTy);
4027 tl_assert(typeOfIRExpr(pce->sb->tyenv, a3) == pce->gWordTy);
4028 tl_assert(typeOfIRExpr(pce->sb->tyenv, a4) == pce->gWordTy);
4029 tl_assert(typeOfIRExpr(pce->sb->tyenv, a5) == pce->gWordTy);
4030 tl_assert(typeOfIRExpr(pce->sb->tyenv, a6) == pce->gWordTy);
4031 di = unsafeIRDirty_0_N( 3/*regparms*/,
4032 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
4033 mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) );
4034 stmt( 'I', pce, IRStmt_Dirty(di) );
4037 static IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a )
4039 IRType a_ty = typeOfIRExpr(pce->sb->tyenv, a);
4040 tl_assert(isIRAtom(a));
4041 if (pce->hWordTy == Ity_I32) {
4044 return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) );
4046 return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) );
4052 tl_assert(pce->hWordTy == Ity_I64);
4055 return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) );
4057 return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) );
4059 return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) );
4067 /* 'e' is a word-sized atom. Call nonptr_or_unknown with it, bind the
4068 results to a new temporary, and return the temporary. Note this
4069 takes an original expression but returns a shadow value. */
4070 static IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e )
4072 return gen_dirty_W_W( pce, &nonptr_or_unknown,
4073 "nonptr_or_unknown", e );
4077 /* Generate the shadow value for an IRExpr which is an atom and
4078 guaranteed to be word-sized. */
4079 static IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e )
4081 if (pce->gWordTy == Ity_I32) {
4082 if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) {
4084 tl_assert(sizeof(UWord) == 4);
4085 t = gen_call_nonptr_or_unknown_w(pce, e);
4088 if (e->tag == Iex_RdTmp
4089 && typeOfIRExpr(pce->sb->tyenv, e) == Ity_I32) {
4090 return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
4092 /* there are no other word-sized atom cases */
4094 if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) {
4096 tl_assert(sizeof(UWord) == 8);
4097 //return mkU64( (ULong)(UWord)NONPTR );
4098 t = gen_call_nonptr_or_unknown_w(pce, e);
4101 if (e->tag == Iex_RdTmp
4102 && typeOfIRExpr(pce->sb->tyenv, e) == Ity_I64) {
4103 return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
4105 /* there are no other word-sized atom cases */
4113 void instrument_arithop ( PCEnv* pce,
4114 IRTemp dst, /* already holds result */
4115 IRTemp dstv, /* generate an assignment to this */
4117 /* original args, guaranteed to be atoms */
4118 IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 )
4124 //IRExpr* a3v = NULL;
4125 //IRExpr* a4v = NULL;
4126 IRTemp res = IRTemp_INVALID;
4128 if (pce->gWordTy == Ity_I32) {
4130 tl_assert(pce->hWordTy == Ity_I32);
4133 /* For these cases, pass Segs for both arguments, and the
4135 case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32;
4136 case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32;
4137 case Iop_Or32: nm = "do_orW"; fn = &do_orW; goto ssr32;
4139 a1v = schemeEw_Atom( pce, a1 );
4140 a2v = schemeEw_Atom( pce, a2 );
4141 res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
4142 assign( 'I', pce, dstv, mkexpr(res) );
4145 /* In this case, pass Segs for both arguments, the result
4146 value, and the difference between the (original) values of
4149 nm = "do_andW"; fn = &do_andW;
4150 a1v = schemeEw_Atom( pce, a1 );
4151 a2v = schemeEw_Atom( pce, a2 );
4152 res = gen_dirty_W_WWWW(
4153 pce, fn, nm, a1v, a2v, mkexpr(dst),
4154 assignNew( 'I', pce, Ity_I32,
4155 binop(Iop_Sub32,a1,a2) ) );
4156 assign( 'I', pce, dstv, mkexpr(res) );
4159 /* Pass one shadow arg and the result to the helper. */
4160 case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32;
4162 a1v = schemeEw_Atom( pce, a1 );
4163 res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
4164 assign( 'I', pce, dstv, mkexpr(res) );
4167 /* Pass two shadow args only to the helper. */
4168 case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32;
4170 a1v = schemeEw_Atom( pce, a1 );
4171 a2v = schemeEw_Atom( pce, a2 );
4172 res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
4173 assign( 'I', pce, dstv, mkexpr(res) );
4176 /* We don't really know what the result could be; test at run
4178 case Iop_64HIto32: goto n_or_u_32;
4179 case Iop_64to32: goto n_or_u_32;
4180 case Iop_Xor32: goto n_or_u_32;
4182 assign( 'I', pce, dstv,
4184 gen_call_nonptr_or_unknown_w( pce,
4188 /* Cases where it's very obvious that the result cannot be a
4189 pointer. Hence declare directly that it's NONPTR; don't
4190 bother with the overhead of calling nonptr_or_unknown. */
4192 /* cases where it makes no sense for the result to be a ptr */
4193 /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
4194 arg, so that shift by zero preserves the original
4196 case Iop_Shl32: goto n32;
4197 case Iop_Sar32: goto n32;
4198 case Iop_Shr32: goto n32;
4199 case Iop_16Uto32: goto n32;
4200 case Iop_16Sto32: goto n32;
4201 case Iop_F64toI32S: goto n32;
4202 case Iop_16HLto32: goto n32;
4203 case Iop_MullS16: goto n32;
4204 case Iop_MullU16: goto n32;
4205 case Iop_PRemC3210F64: goto n32;
4206 case Iop_DivU32: goto n32;
4207 case Iop_DivS32: goto n32;
4208 case Iop_V128to32: goto n32;
4210 /* cases where result range is very limited and clearly cannot
4212 case Iop_1Uto32: goto n32;
4213 case Iop_1Sto32: goto n32;
4214 case Iop_8Uto32: goto n32;
4215 case Iop_8Sto32: goto n32;
4216 case Iop_Clz32: goto n32;
4217 case Iop_Ctz32: goto n32;
4218 case Iop_CmpF64: goto n32;
4219 case Iop_CmpORD32S: goto n32;
4220 case Iop_CmpORD32U: goto n32;
4222 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4226 VG_(printf)("instrument_arithop(32-bit): unhandled: ");
4233 tl_assert(pce->gWordTy == Ity_I64);
4236 /* For these cases, pass Segs for both arguments, and the
4238 case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64;
4239 case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64;
4240 case Iop_Or64: nm = "do_orW"; fn = &do_orW; goto ssr64;
4242 a1v = schemeEw_Atom( pce, a1 );
4243 a2v = schemeEw_Atom( pce, a2 );
4244 res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
4245 assign( 'I', pce, dstv, mkexpr(res) );
4248 /* In this case, pass Segs for both arguments, the result
4249 value, and the difference between the (original) values of
4252 nm = "do_andW"; fn = &do_andW;
4253 a1v = schemeEw_Atom( pce, a1 );
4254 a2v = schemeEw_Atom( pce, a2 );
4255 res = gen_dirty_W_WWWW(
4256 pce, fn, nm, a1v, a2v, mkexpr(dst),
4257 assignNew( 'I', pce, Ity_I64,
4258 binop(Iop_Sub64,a1,a2) ) );
4259 assign( 'I', pce, dstv, mkexpr(res) );
4262 /* Pass one shadow arg and the result to the helper. */
4263 case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64;
4265 a1v = schemeEw_Atom( pce, a1 );
4266 res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
4267 assign( 'I', pce, dstv, mkexpr(res) );
4270 /* Pass two shadow args only to the helper. */
4271 case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64;
4273 a1v = schemeEw_Atom( pce, a1 );
4274 a2v = schemeEw_Atom( pce, a2 );
4275 res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
4276 assign( 'I', pce, dstv, mkexpr(res) );
4279 /* We don't really know what the result could be; test at run
4281 case Iop_Xor64: goto n_or_u_64;
4282 case Iop_128HIto64: goto n_or_u_64;
4283 case Iop_128to64: goto n_or_u_64;
4284 case Iop_V128HIto64: goto n_or_u_64;
4285 case Iop_V128to64: goto n_or_u_64;
4287 assign( 'I', pce, dstv,
4289 gen_call_nonptr_or_unknown_w( pce,
4293 /* Cases where it's very obvious that the result cannot be a
4294 pointer. Hence declare directly that it's NONPTR; don't
4295 bother with the overhead of calling nonptr_or_unknown. */
4297 /* cases where it makes no sense for the result to be a ptr */
4298 /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
4299 arg, so that shift by zero preserves the original
4301 case Iop_Shl64: goto n64;
4302 case Iop_Sar64: goto n64;
4303 case Iop_Shr64: goto n64;
4304 case Iop_32Uto64: goto n64;
4305 case Iop_32Sto64: goto n64;
4306 case Iop_16Uto64: goto n64;
4307 case Iop_16Sto64: goto n64;
4308 case Iop_32HLto64: goto n64;
4309 case Iop_DivModU64to32: goto n64;
4310 case Iop_DivModS64to32: goto n64;
4311 case Iop_F64toI64S: goto n64;
4312 case Iop_MullS32: goto n64;
4313 case Iop_MullU32: goto n64;
4314 case Iop_DivU64: goto n64;
4315 case Iop_DivS64: goto n64;
4316 case Iop_ReinterpF64asI64: goto n64;
4318 /* cases where result range is very limited and clearly cannot
4320 case Iop_1Uto64: goto n64;
4321 case Iop_8Uto64: goto n64;
4322 case Iop_8Sto64: goto n64;
4323 case Iop_Ctz64: goto n64;
4324 case Iop_Clz64: goto n64;
4325 case Iop_CmpORD64S: goto n64;
4326 case Iop_CmpORD64U: goto n64;
4328 case Iop_Avg8Ux8: case Iop_Avg16Ux4:
4329 case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4:
4330 case Iop_Min8Ux8: case Iop_MulHi16Ux4:
4331 case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4:
4332 case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2:
4333 case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8:
4334 case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8:
4335 case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8:
4336 case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4:
4337 case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4:
4338 case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2:
4339 case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2:
4340 case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8:
4341 case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8:
4342 case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4:
4343 case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2:
4344 case Iop_InterleaveLO16x4: case Iop_SarN8x8:
4345 case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2:
4346 case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4:
4348 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4352 VG_(printf)("instrument_arithop(64-bit): unhandled: ");
4360 void gen_call_nonptr_or_unknown_range ( PCEnv* pce,
4362 IRAtom* addr, IRAtom* len )
4364 gen_dirty_v_WW( pce, guard,
4365 &nonptr_or_unknown_range,
4366 "nonptr_or_unknown_range",
4370 /* iii describes zero or more non-exact integer register updates. For
4371 each one, generate IR to get the containing register, apply
4372 nonptr_or_unknown to it, and write it back again. */
4373 static void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii )
4376 tl_assert(iii && iii->n_offsets >= 0);
4377 for (i = 0; i < iii->n_offsets; i++) {
4378 IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy,
4379 IRExpr_Get( iii->offsets[i], pce->gWordTy ));
4380 IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4381 stmt( 'I', pce, IRStmt_Put( iii->offsets[i]
4382 + pce->guest_state_sizeB,
4388 /* schemeS helper for doing stores, pulled out into a function because
4389 it needs to handle both normal stores and store-conditionals.
4390 Returns False if we see a case we don't know how to handle.
4392 static Bool schemeS_store ( PCEnv* pce,
4393 IRExpr* data, IRExpr* addr, IRTemp resSC )
4395 /* We have: STle(addr) = data
4396 if data is int-word sized, do
4397 check_store4(addr, addr#, data, data#)
4398 for all other stores
4399 check_store{1,2}(addr, addr#, data)
4401 The helper actually *does* the store, so that it can do the
4402 post-hoc ugly hack of inspecting and "improving" the shadow data
4403 after the store, in the case where it isn't an aligned word
4406 Only word-sized values are shadowed. If this is a
4407 store-conditional, .resSC will denote a non-word-typed temp, and
4408 so we don't need to shadow it. Assert about the type, tho.
4409 However, since we're not re-emitting the original IRStmt_Store,
4410 but rather doing it as part of the helper function, we need to
4411 actually do a SC in the helper, and assign the result bit to
4414 IRType d_ty = typeOfIRExpr(pce->sb->tyenv, data);
4415 IRExpr* addrv = schemeEw_Atom( pce, addr );
4416 if (resSC != IRTemp_INVALID) {
4417 tl_assert(typeOfIRTemp(pce->sb->tyenv, resSC) == Ity_I1);
4418 /* viz, not something we want to shadow */
4419 /* also, throw out all store-conditional cases that
4421 if (pce->gWordTy == Ity_I32 && d_ty != Ity_I32)
4423 if (pce->gWordTy == Ity_I64 && d_ty != Ity_I32 && d_ty != Ity_I64)
4426 if (pce->gWordTy == Ity_I32) {
4427 /* ------ 32 bit host/guest (cough, cough) ------ */
4429 /* Integer word case */
4431 IRExpr* datav = schemeEw_Atom( pce, data );
4432 if (resSC == IRTemp_INVALID) {
4433 /* "normal" store */
4434 gen_dirty_v_WWWW( pce,
4435 &check_store4_P, "check_store4_P",
4436 addr, addrv, data, datav );
4438 /* store-conditional; need to snarf the success bit */
4440 = gen_dirty_W_WWWW( pce,
4443 addr, addrv, data, datav );
4444 /* presumably resSC32 will really be Ity_I32. In
4445 any case we'll get jumped by the IR sanity
4446 checker if it's not, when it sees the
4447 following statement. */
4448 assign( 'I', pce, resSC, unop(Iop_32to1, mkexpr(resSC32)) );
4452 /* Integer subword cases */
4454 gen_dirty_v_WWW( pce,
4455 &check_store2, "check_store2",
4457 uwiden_to_host_word( pce, data ));
4460 gen_dirty_v_WWW( pce,
4461 &check_store1, "check_store1",
4463 uwiden_to_host_word( pce, data ));
4465 /* 64-bit float. Pass store data in 2 32-bit pieces. */
4467 IRAtom* d64 = assignNew( 'I', pce, Ity_I64,
4468 unop(Iop_ReinterpF64asI64, data) );
4469 IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4470 unop(Iop_64to32, d64) );
4471 IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4472 unop(Iop_64HIto32, d64) );
4473 gen_dirty_v_WWWW( pce,
4474 &check_store8_ms4B_ls4B,
4475 "check_store8_ms4B_ls4B",
4476 addr, addrv, dHi32, dLo32 );
4479 /* 32-bit float. We can just use _store4, but need
4480 to futz with the argument type. */
4482 IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4483 unop(Iop_ReinterpF32asI32,
4485 gen_dirty_v_WWW( pce,
4491 /* 64-bit int. Pass store data in 2 32-bit pieces. */
4493 IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4494 unop(Iop_64to32, data) );
4495 IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4496 unop(Iop_64HIto32, data) );
4497 gen_dirty_v_WWWW( pce,
4498 &check_store8_ms4B_ls4B,
4499 "check_store8_ms4B_ls4B",
4500 addr, addrv, dHi32, dLo32 );
4503 /* 128-bit vector. Pass store data in 4 32-bit pieces.
4504 This is all very ugly and inefficient, but it is
4505 hard to better without considerably complicating the
4506 store-handling schemes. */
4508 IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4509 unop(Iop_V128HIto64, data) );
4510 IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4511 unop(Iop_V128to64, data) );
4512 IRAtom* w3 = assignNew( 'I', pce, Ity_I32,
4513 unop(Iop_64HIto32, dHi64) );
4514 IRAtom* w2 = assignNew( 'I', pce, Ity_I32,
4515 unop(Iop_64to32, dHi64) );
4516 IRAtom* w1 = assignNew( 'I', pce, Ity_I32,
4517 unop(Iop_64HIto32, dLo64) );
4518 IRAtom* w0 = assignNew( 'I', pce, Ity_I32,
4519 unop(Iop_64to32, dLo64) );
4520 gen_dirty_v_6W( pce,
4521 &check_store16_ms4B_4B_4B_ls4B,
4522 "check_store16_ms4B_4B_4B_ls4B",
4523 addr, addrv, w3, w2, w1, w0 );
4527 ppIRType(d_ty); tl_assert(0);
4530 /* ------ 64 bit host/guest (cough, cough) ------ */
4532 /* Integer word case */
4534 IRExpr* datav = schemeEw_Atom( pce, data );
4535 if (resSC == IRTemp_INVALID) {
4536 /* "normal" store */
4537 gen_dirty_v_WWWW( pce,
4538 &check_store8_P, "check_store8_P",
4539 addr, addrv, data, datav );
4542 = gen_dirty_W_WWWW( pce,
4545 addr, addrv, data, datav );
4546 assign( 'I', pce, resSC, unop(Iop_64to1, mkexpr(resSC64)) );
4550 /* Integer subword cases */
4552 if (resSC == IRTemp_INVALID) {
4553 /* "normal" store */
4554 gen_dirty_v_WWW( pce,
4555 &check_store4, "check_store4",
4557 uwiden_to_host_word( pce, data ));
4559 /* store-conditional; need to snarf the success bit */
4561 = gen_dirty_W_WWW( pce,
4565 uwiden_to_host_word( pce, data ));
4566 assign( 'I', pce, resSC, unop(Iop_64to1, mkexpr(resSC64)) );
4570 gen_dirty_v_WWW( pce,
4571 &check_store2, "check_store2",
4573 uwiden_to_host_word( pce, data ));
4576 gen_dirty_v_WWW( pce,
4577 &check_store1, "check_store1",
4579 uwiden_to_host_word( pce, data ));
4581 /* 128-bit vector. Pass store data in 2 64-bit pieces. */
4583 IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4584 unop(Iop_V128HIto64, data) );
4585 IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4586 unop(Iop_V128to64, data) );
4587 gen_dirty_v_WWWW( pce,
4588 &check_store16_ms8B_ls8B,
4589 "check_store16_ms8B_ls8B",
4590 addr, addrv, dHi64, dLo64 );
4595 IRAtom* dI = assignNew( 'I', pce, Ity_I64,
4596 unop(Iop_ReinterpF64asI64,
4598 gen_dirty_v_WWW( pce,
4599 &check_store8_all8B,
4600 "check_store8_all8B",
4604 /* 32-bit float. We can just use _store4, but need
4605 to futz with the argument type. */
4607 IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4608 unop(Iop_ReinterpF32asI32,
4610 IRAtom* i64 = assignNew( 'I', pce, Ity_I64,
4613 gen_dirty_v_WWW( pce,
4620 ppIRType(d_ty); tl_assert(0);
4623 /* And don't copy the original, since the helper does the store.
4625 return True; /* store was successfully instrumented */
4629 /* schemeS helper for doing loads, pulled out into a function because
4630 it needs to handle both normal loads and load-linked's.
4632 static void schemeS_load ( PCEnv* pce, IRExpr* addr, IRType e_ty, IRTemp dstv )
4636 IRExpr* addrv = NULL;
4637 if (e_ty == pce->gWordTy) {
4638 tl_assert(dstv != IRTemp_INVALID);
4640 tl_assert(dstv == IRTemp_INVALID);
4642 if (pce->gWordTy == Ity_I32) {
4643 /* 32 bit host/guest (cough, cough) */
4645 /* Ity_I32: helper returns shadow value. */
4646 case Ity_I32: h_fn = &check_load4_P;
4647 h_nm = "check_load4_P"; break;
4648 /* all others: helper does not return a shadow
4650 case Ity_V128: h_fn = &check_load16;
4651 h_nm = "check_load16"; break;
4653 case Ity_F64: h_fn = &check_load8;
4654 h_nm = "check_load8"; break;
4655 case Ity_F32: h_fn = &check_load4;
4656 h_nm = "check_load4"; break;
4657 case Ity_I16: h_fn = &check_load2;
4658 h_nm = "check_load2"; break;
4659 case Ity_I8: h_fn = &check_load1;
4660 h_nm = "check_load1"; break;
4661 default: ppIRType(e_ty); tl_assert(0);
4663 addrv = schemeEw_Atom( pce, addr );
4664 if (e_ty == Ity_I32) {
4665 assign( 'I', pce, dstv,
4666 mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4669 gen_dirty_v_WW( pce, NULL, h_fn, h_nm, addr, addrv );
4672 /* 64 bit host/guest (cough, cough) */
4674 /* Ity_I64: helper returns shadow value. */
4675 case Ity_I64: h_fn = &check_load8_P;
4676 h_nm = "check_load8_P"; break;
4677 /* all others: helper does not return a shadow
4679 case Ity_V128: h_fn = &check_load16;
4680 h_nm = "check_load16"; break;
4681 case Ity_F64: h_fn = &check_load8;
4682 h_nm = "check_load8"; break;
4684 case Ity_I32: h_fn = &check_load4;
4685 h_nm = "check_load4"; break;
4686 case Ity_I16: h_fn = &check_load2;
4687 h_nm = "check_load2"; break;
4688 case Ity_I8: h_fn = &check_load1;
4689 h_nm = "check_load1"; break;
4690 default: ppIRType(e_ty); tl_assert(0);
4692 addrv = schemeEw_Atom( pce, addr );
4693 if (e_ty == Ity_I64) {
4694 assign( 'I', pce, dstv,
4695 mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4698 gen_dirty_v_WW( pce, NULL, h_fn, h_nm, addr, addrv );
4704 /* Generate into 'pce', instrumentation for 'st'. Also copy 'st'
4705 itself into 'pce' (the caller does not do so). This is somewhat
4706 complex and relies heavily on the assumption that the incoming IR
4709 Generally speaking, the instrumentation is placed after the
4710 original statement, so that results computed by the original can be
4711 used in the instrumentation. However, that isn't safe for memory
4712 references, since we need the instrumentation (hence bounds check
4713 and potential error message) to happen before the reference itself,
4714 as the latter could cause a fault. */
4715 static void schemeS ( PCEnv* pce, IRStmt* st )
4718 tl_assert(isFlatIRStmt(st));
4723 /* In all these CAS cases, the did-we-succeed? comparison is
4724 done using Iop_CasCmpEQ{8,16,32,64} rather than the plain
4725 Iop_CmpEQ equivalents. This isn't actually necessary,
4726 since the generated IR is not going to be subsequently
4727 instrumented by Memcheck. But it's done for consistency.
4728 See COMMENT_ON_CasCmpEQ in memcheck/mc_translate.c for
4729 background/rationale. */
4730 IRCAS* cas = st->Ist.CAS.details;
4731 IRType elTy = typeOfIRExpr(pce->sb->tyenv, cas->expdLo);
4732 if (cas->oldHi == IRTemp_INVALID) {
4733 /* ------------ SINGLE CAS ------------ */
4734 /* -- single cas -- 32 bits, on 32-bit host -- */
4735 /* -- single cas -- 64 bits, on 64-bit host -- */
4736 /* -- viz, single cas, native-word case -- */
4737 if ( (pce->gWordTy == Ity_I32 && elTy == Ity_I32)
4738 || (pce->gWordTy == Ity_I64 && elTy == Ity_I64) ) {
4739 // 32 bit host translation scheme; 64-bit is analogous
4740 // old# = check_load4_P(addr, addr#)
4741 // old = CAS(addr:expd->new) [COPY]
4742 // success = CasCmpEQ32(old,expd)
4743 // if (success) do_shadow_store4_P(addr, new#)
4745 Bool is64 = elTy == Ity_I64;
4746 IROp cmpEQ = is64 ? Iop_CasCmpEQ64 : Iop_CasCmpEQ32;
4747 void* r_fn = is64 ? &check_load8_P : &check_load4_P;
4748 HChar* r_nm = is64 ? "check_load8_P" : "check_load4_P";
4749 void* w_fn = is64 ? &do_shadow_store8_P : &do_shadow_store4_P;
4750 void* w_nm = is64 ? "do_shadow_store8_P" : "do_shadow_store4_P";
4751 IRExpr* addr = cas->addr;
4752 IRExpr* addrV = schemeEw_Atom(pce, addr);
4753 IRTemp old = cas->oldLo;
4754 IRTemp oldV = newShadowTmp(pce, old);
4755 IRExpr* nyu = cas->dataLo;
4756 IRExpr* nyuV = schemeEw_Atom(pce, nyu);
4757 IRExpr* expd = cas->expdLo;
4758 assign( 'I', pce, oldV,
4759 mkexpr( gen_dirty_W_WW( pce, r_fn, r_nm, addr, addrV )));
4760 stmt( 'C', pce, st );
4761 success = newTemp(pce, Ity_I1, NonShad);
4762 assign('I', pce, success, binop(cmpEQ, mkexpr(old), expd));
4763 gen_dirty_v_WW( pce, mkexpr(success), w_fn, w_nm, addr, nyuV );
4766 /* -- single cas -- 8 or 16 bits, on 32-bit host -- */
4767 /* -- viz, single cas, 32-bit subword cases -- */
4768 if (pce->gWordTy == Ity_I32
4769 && (elTy == Ity_I8 || elTy == Ity_I16)) {
4770 // 8-bit translation scheme; 16-bit is analogous
4771 // check_load1(addr, addr#)
4772 // old = CAS(addr:expd->new) [COPY]
4773 // success = CasCmpEQ8(old,expd)
4774 // if (success) nonptr_or_unknown_range(addr, 1)
4776 Bool is16 = elTy == Ity_I16;
4777 IRExpr* addr = cas->addr;
4778 IRExpr* addrV = schemeEw_Atom(pce, addr);
4779 IRTemp old = cas->oldLo;
4780 IRExpr* expd = cas->expdLo;
4781 void* h_fn = is16 ? &check_load2 : &check_load1;
4782 HChar* h_nm = is16 ? "check_load2" : "check_load1";
4783 IROp cmpEQ = is16 ? Iop_CasCmpEQ16 : Iop_CasCmpEQ8;
4784 Int szB = is16 ? 2 : 1;
4785 gen_dirty_v_WW( pce, NULL, h_fn, h_nm, addr, addrV );
4786 stmt( 'C', pce, st );
4787 success = newTemp(pce, Ity_I1, NonShad);
4788 assign('I', pce, success,
4789 binop(cmpEQ, mkexpr(old), expd));
4790 gen_call_nonptr_or_unknown_range( pce, mkexpr(success),
4791 addr, mkIRExpr_HWord(szB) );
4794 /* -- single cas -- 8, 16 or 32 bits, on 64-bit host -- */
4795 /* -- viz, single cas, 64-bit subword cases -- */
4796 if (pce->gWordTy == Ity_I64
4797 && (elTy == Ity_I8 || elTy == Ity_I16 || elTy == Ity_I32)) {
4798 // 8-bit translation scheme; 16/32-bit are analogous
4799 // check_load1(addr, addr#)
4800 // old = CAS(addr:expd->new) [COPY]
4801 // success = CasCmpEQ8(old,expd)
4802 // if (success) nonptr_or_unknown_range(addr, 1)
4804 Bool is16 = elTy == Ity_I16;
4805 Bool is32 = elTy == Ity_I32;
4806 IRExpr* addr = cas->addr;
4807 IRExpr* addrV = schemeEw_Atom(pce, addr);
4808 IRTemp old = cas->oldLo;
4809 IRExpr* expd = cas->expdLo;
4810 void* h_fn = is32 ? &check_load4
4811 : (is16 ? &check_load2 : &check_load1);
4812 HChar* h_nm = is32 ? "check_load4"
4813 : (is16 ? "check_load2" : "check_load1");
4814 IROp cmpEQ = is32 ? Iop_CasCmpEQ32
4815 : (is16 ? Iop_CasCmpEQ16 : Iop_CasCmpEQ8);
4816 Int szB = is32 ? 4 : (is16 ? 2 : 1);
4817 gen_dirty_v_WW( pce, NULL, h_fn, h_nm, addr, addrV );
4818 stmt( 'C', pce, st );
4819 success = newTemp(pce, Ity_I1, NonShad);
4820 assign('I', pce, success,
4821 binop(cmpEQ, mkexpr(old), expd));
4822 gen_call_nonptr_or_unknown_range( pce, mkexpr(success),
4823 addr, mkIRExpr_HWord(szB) );
4828 /* ------------ DOUBLE CAS ------------ */
4829 /* Punt on bigendian DCAS. In fact it's probably trivial
4830 to do; just swap the individual shadow loads/stores
4831 around in memory, but we'd have to verify it, and there
4832 is no use case. So punt. */
4833 if (cas->end != Iend_LE)
4835 /* -- double cas -- 2 x 32 bits, on 32-bit host -- */
4836 /* -- double cas -- 2 x 64 bits, on 64-bit host -- */
4837 /* -- viz, double cas, native-word case -- */
4838 if ( (pce->gWordTy == Ity_I32 && elTy == Ity_I32)
4839 || (pce->gWordTy == Ity_I64 && elTy == Ity_I64) ) {
4840 // 32 bit host translation scheme; 64-bit is analogous
4841 // oldHi# = check_load4_P(addr+4, addr#)
4842 // oldLo# = check_load4_P(addr+0, addr#)
4843 // oldHi/Lo = DCAS(addr:expdHi/Lo->newHi/Lo) [COPY]
4844 // success = CasCmpEQ32(oldHi,expdHi) && CasCmpEQ32(oldLo,expdLo)
4845 // = ((oldHi ^ expdHi) | (oldLo ^ expdLo)) == 0
4846 // if (success) do_shadow_store4_P(addr+4, newHi#)
4847 // if (success) do_shadow_store4_P(addr+0, newLo#)
4848 IRTemp diffHi, diffLo, diff, success, addrpp;
4849 Bool is64 = elTy == Ity_I64;
4850 void* r_fn = is64 ? &check_load8_P : &check_load4_P;
4851 HChar* r_nm = is64 ? "check_load8_P" : "check_load4_P";
4852 void* w_fn = is64 ? &do_shadow_store8_P
4853 : &do_shadow_store4_P;
4854 void* w_nm = is64 ? "do_shadow_store8_P"
4855 : "do_shadow_store4_P";
4856 IROp opADD = is64 ? Iop_Add64 : Iop_Add32;
4857 IROp opXOR = is64 ? Iop_Xor64 : Iop_Xor32;
4858 IROp opOR = is64 ? Iop_Or64 : Iop_Or32;
4859 IROp opCasCmpEQ = is64 ? Iop_CasCmpEQ64 : Iop_CasCmpEQ32;
4860 IRExpr* step = is64 ? mkU64(8) : mkU32(4);
4861 IRExpr* zero = is64 ? mkU64(0) : mkU32(0);
4862 IRExpr* addr = cas->addr;
4863 IRExpr* addrV = schemeEw_Atom(pce, addr);
4864 IRTemp oldLo = cas->oldLo;
4865 IRTemp oldLoV = newShadowTmp(pce, oldLo);
4866 IRTemp oldHi = cas->oldHi;
4867 IRTemp oldHiV = newShadowTmp(pce, oldHi);
4868 IRExpr* nyuLo = cas->dataLo;
4869 IRExpr* nyuLoV = schemeEw_Atom(pce, nyuLo);
4870 IRExpr* nyuHi = cas->dataHi;
4871 IRExpr* nyuHiV = schemeEw_Atom(pce, nyuHi);
4872 IRExpr* expdLo = cas->expdLo;
4873 IRExpr* expdHi = cas->expdHi;
4874 tl_assert(elTy == Ity_I32 || elTy == Ity_I64);
4875 tl_assert(pce->gWordTy == elTy);
4876 addrpp = newTemp(pce, elTy, NonShad);
4877 assign('I', pce, addrpp, binop(opADD, addr, step));
4878 assign('I', pce, oldHiV,
4879 mkexpr( gen_dirty_W_WW( pce, r_fn, r_nm,
4880 mkexpr(addrpp), addrV ))
4882 assign('I', pce, oldLoV,
4883 mkexpr( gen_dirty_W_WW( pce, r_fn, r_nm,
4886 stmt( 'C', pce, st );
4887 diffHi = newTemp(pce, elTy, NonShad);
4888 assign('I', pce, diffHi,
4889 binop(opXOR, mkexpr(oldHi), expdHi));
4890 diffLo = newTemp(pce, elTy, NonShad);
4891 assign('I', pce, diffLo,
4892 binop(opXOR, mkexpr(oldLo), expdLo));
4893 diff = newTemp(pce, elTy, NonShad);
4894 assign('I', pce, diff,
4895 binop(opOR, mkexpr(diffHi), mkexpr(diffLo)));
4896 success = newTemp(pce, Ity_I1, NonShad);
4897 assign('I', pce, success,
4898 binop(opCasCmpEQ, mkexpr(diff), zero));
4899 gen_dirty_v_WW( pce, mkexpr(success),
4900 w_fn, w_nm, mkexpr(addrpp), nyuHiV );
4901 gen_dirty_v_WW( pce, mkexpr(success),
4902 w_fn, w_nm, addr, nyuLoV );
4905 /* -- double cas -- 2 x 32 bits, on 64-bit host -- */
4906 if (pce->gWordTy == Ity_I64 && elTy == Ity_I32) {
4907 // check_load8(addr, addr#)
4908 // oldHi/Lo = DCAS(addr:expdHi/Lo->newHi/Lo) [COPY]
4909 // success = CasCmpEQ32(oldHi,expdHi) && CasCmpEQ32(oldLo,expdLo)
4910 // = ((oldHi ^ expdHi) | (oldLo ^ expdLo)) == 0
4911 // if (success) nonptr_or_unknown_range(addr, 8)
4912 IRTemp diffHi, diffLo, diff, success;
4913 IRExpr* addr = cas->addr;
4914 IRExpr* addrV = schemeEw_Atom(pce, addr);
4915 IRTemp oldLo = cas->oldLo;
4916 IRTemp oldHi = cas->oldHi;
4917 IRExpr* expdLo = cas->expdLo;
4918 IRExpr* expdHi = cas->expdHi;
4919 gen_dirty_v_WW( pce, NULL, &check_load8, "check_load8",
4921 stmt( 'C', pce, st );
4922 diffHi = newTemp(pce, Ity_I32, NonShad);
4923 assign('I', pce, diffHi,
4924 binop(Iop_Xor32, mkexpr(oldHi), expdHi));
4925 diffLo = newTemp(pce, Ity_I32, NonShad);
4926 assign('I', pce, diffLo,
4927 binop(Iop_Xor32, mkexpr(oldLo), expdLo));
4928 diff = newTemp(pce, Ity_I32, NonShad);
4929 assign('I', pce, diff,
4930 binop(Iop_Or32, mkexpr(diffHi), mkexpr(diffLo)));
4931 success = newTemp(pce, Ity_I1, NonShad);
4932 assign('I', pce, success,
4933 binop(Iop_CasCmpEQ32, mkexpr(diff), mkU32(0)));
4934 gen_call_nonptr_or_unknown_range( pce, mkexpr(success),
4944 if (st->Ist.LLSC.storedata == NULL) {
4946 IRTemp dst = st->Ist.LLSC.result;
4947 IRType dataTy = typeOfIRTemp(pce->sb->tyenv, dst);
4948 Bool isWord = dataTy == pce->gWordTy;
4949 IRTemp dstv = isWord ? newShadowTmp( pce, dst )
4951 schemeS_load( pce, st->Ist.LLSC.addr, dataTy, dstv );
4952 /* copy the original -- must happen after the helper call */
4953 stmt( 'C', pce, st );
4957 st->Ist.LLSC.storedata,
4959 st->Ist.LLSC.result );
4960 /* Don't copy the original, since the helper does the
4969 stmt( 'C', pce, st );
4970 /* nasty. assumes that (1) all helpers are unconditional,
4971 and (2) all outputs are non-ptr */
4972 di = st->Ist.Dirty.details;
4973 /* deal with the return tmp, if any */
4974 if (di->tmp != IRTemp_INVALID
4975 && typeOfIRTemp(pce->sb->tyenv, di->tmp) == pce->gWordTy) {
4976 /* di->tmp is shadowed. Set it to NONPTR. */
4977 IRTemp dstv = newShadowTmp( pce, di->tmp );
4978 if (pce->gWordTy == Ity_I32) {
4979 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4981 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4984 /* apply the nonptr_or_unknown technique to any parts of
4985 the guest state that happen to get written */
4986 for (i = 0; i < di->nFxState; i++) {
4988 tl_assert(di->fxState[i].fx != Ifx_None);
4989 if (di->fxState[i].fx == Ifx_Read)
4990 continue; /* this bit is only read -- not interesting */
4991 get_IntRegInfo( &iii, di->fxState[i].offset,
4992 di->fxState[i].size );
4993 tl_assert(iii.n_offsets >= -1
4994 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4995 /* Deal with 3 possible cases, same as with Ist_Put
4996 elsewhere in this function. */
4997 if (iii.n_offsets == -1) {
4998 /* case (1): exact write of an integer register. */
5000 = assignNew( 'I', pce, pce->gWordTy,
5001 IRExpr_Get( iii.offsets[i], pce->gWordTy ));
5002 IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
5003 stmt( 'I', pce, IRStmt_Put( iii.offsets[i]
5004 + pce->guest_state_sizeB,
5007 /* when == 0: case (3): no instrumentation needed */
5008 /* when > 0: case (2) .. complex case. Fish out the
5009 stored value for the whole register, heave it
5010 through nonptr_or_unknown, and use that as the new
5012 tl_assert(iii.n_offsets >= 0
5013 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
5014 gen_nonptr_or_unknown_for_III( pce, &iii );
5016 } /* for (i = 0; i < di->nFxState; i++) */
5017 /* finally, deal with memory outputs */
5018 if (di->mFx != Ifx_None) {
5019 tl_assert(di->mAddr && isIRAtom(di->mAddr));
5020 tl_assert(di->mSize > 0);
5021 gen_call_nonptr_or_unknown_range( pce, NULL, di->mAddr,
5022 mkIRExpr_HWord(di->mSize));
5030 /* nothing interesting in these; just copy them through */
5035 stmt( 'C', pce, st );
5039 IRRegArray* descr = st->Ist.PutI.descr;
5040 stmt( 'C', pce, st );
5041 tl_assert(descr && descr->elemTy);
5042 if (is_integer_guest_reg_array(descr)) {
5043 /* if this fails, is_integer_guest_reg_array is returning
5045 tl_assert(descr->elemTy == pce->gWordTy);
5049 mkIRRegArray(descr->base + pce->guest_state_sizeB,
5050 descr->elemTy, descr->nElems),
5053 schemeEw_Atom( pce, st->Ist.PutI.data)
5061 /* PUT(offset) = atom */
5063 1. It's a complete write of an integer register. Get hold of
5064 'atom's shadow value and write it in the shadow state.
5065 2. It's a partial write of an integer register. Let the write
5066 happen, then fish out the complete register value and see if,
5067 via range checking, consultation of tea leaves, etc, its
5068 shadow value can be upgraded to anything useful.
5069 3. It is none of the above. Generate no instrumentation. */
5072 stmt( 'C', pce, st );
5073 ty = typeOfIRExpr(pce->sb->tyenv, st->Ist.Put.data);
5074 get_IntRegInfo( &iii, st->Ist.Put.offset,
5076 if (iii.n_offsets == -1) {
5077 /* case (1): exact write of an integer register. */
5078 tl_assert(ty == pce->gWordTy);
5080 IRStmt_Put( st->Ist.Put.offset
5081 + pce->guest_state_sizeB,
5082 schemeEw_Atom( pce, st->Ist.Put.data)) );
5084 /* when == 0: case (3): no instrumentation needed */
5085 /* when > 0: case (2) .. complex case. Fish out the
5086 stored value for the whole register, heave it through
5087 nonptr_or_unknown, and use that as the new shadow
5089 tl_assert(iii.n_offsets >= 0
5090 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
5091 gen_nonptr_or_unknown_for_III( pce, &iii );
5094 } /* case Ist_Put */
5097 Bool ok = schemeS_store( pce,
5100 IRTemp_INVALID/*not a SC*/ );
5101 if (!ok) goto unhandled;
5102 /* Don't copy the original, since the helper does the store
5108 /* This is the only place we have to deal with the full
5109 IRExpr range. In all other places where an IRExpr could
5110 appear, we in fact only get an atom (Iex_RdTmp or
5112 IRExpr* e = st->Ist.WrTmp.data;
5113 IRType e_ty = typeOfIRExpr( pce->sb->tyenv, e );
5114 Bool isWord = e_ty == pce->gWordTy;
5115 IRTemp dst = st->Ist.WrTmp.tmp;
5116 IRTemp dstv = isWord ? newShadowTmp( pce, dst )
5122 stmt( 'C', pce, st );
5124 assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) );
5129 stmt( 'C', pce, st );
5131 assign( 'I', pce, dstv,
5132 mkexpr( gen_call_nonptr_or_unknown_w(
5133 pce, mkexpr(dst))));
5138 /* Just steer the shadow values in the same way as the
5140 stmt( 'C', pce, st );
5142 assign( 'I', pce, dstv,
5145 schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ),
5146 schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) ));
5151 stmt( 'C', pce, st );
5153 assign( 'I', pce, dstv, schemeEw_Atom( pce, e ));
5158 schemeS_load( pce, e->Iex.Load.addr, e_ty, dstv );
5159 /* copy the original -- must happen after the helper call */
5160 stmt( 'C', pce, st );
5165 IRRegArray* descr = e->Iex.GetI.descr;
5166 stmt( 'C', pce, st );
5167 tl_assert(descr && descr->elemTy);
5168 if (is_integer_guest_reg_array(descr)) {
5169 /* if this fails, is_integer_guest_reg_array is
5170 returning bogus results */
5175 mkIRRegArray(descr->base + pce->guest_state_sizeB,
5176 descr->elemTy, descr->nElems),
5186 stmt( 'C', pce, st );
5188 /* guest-word-typed tmp assignment, so it will have a
5189 shadow tmp, and we must make an assignment to
5191 if (is_integer_guest_reg(e->Iex.Get.offset,
5192 sizeofIRType(e->Iex.Get.ty))) {
5193 assign( 'I', pce, dstv,
5194 IRExpr_Get( e->Iex.Get.offset
5195 + pce->guest_state_sizeB,
5198 if (pce->hWordTy == Ity_I32) {
5199 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
5201 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
5205 /* tmp isn't guest-word-typed, so isn't shadowed, so
5206 generate no instrumentation */
5212 stmt( 'C', pce, st );
5213 tl_assert(isIRAtom(e->Iex.Unop.arg));
5215 instrument_arithop( pce, dst, dstv, e->Iex.Unop.op,
5222 stmt( 'C', pce, st );
5223 tl_assert(isIRAtom(e->Iex.Binop.arg1));
5224 tl_assert(isIRAtom(e->Iex.Binop.arg2));
5226 instrument_arithop( pce, dst, dstv, e->Iex.Binop.op,
5227 e->Iex.Binop.arg1, e->Iex.Binop.arg2,
5233 stmt( 'C', pce, st );
5234 tl_assert(isIRAtom(e->Iex.Triop.arg1));
5235 tl_assert(isIRAtom(e->Iex.Triop.arg2));
5236 tl_assert(isIRAtom(e->Iex.Triop.arg3));
5238 instrument_arithop( pce, dst, dstv, e->Iex.Triop.op,
5239 e->Iex.Triop.arg1, e->Iex.Triop.arg2,
5240 e->Iex.Triop.arg3, NULL );
5245 stmt( 'C', pce, st );
5246 tl_assert(isIRAtom(e->Iex.Qop.arg1));
5247 tl_assert(isIRAtom(e->Iex.Qop.arg2));
5248 tl_assert(isIRAtom(e->Iex.Qop.arg3));
5249 tl_assert(isIRAtom(e->Iex.Qop.arg4));
5251 instrument_arithop( pce, dst, dstv, e->Iex.Qop.op,
5252 e->Iex.Qop.arg1, e->Iex.Qop.arg2,
5253 e->Iex.Qop.arg3, e->Iex.Qop.arg4 );
5259 } /* switch (e->tag) */
5263 } /* case Ist_WrTmp */
5273 static IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque )
5275 PCEnv* pce = (PCEnv*)opaque;
5276 return newTemp( pce, ty, NonShad );
5280 IRSB* h_instrument ( VgCallbackClosure* closure,
5282 VexGuestLayout* layout,
5283 VexGuestExtents* vge,
5284 IRType gWordTy, IRType hWordTy )
5286 Bool verboze = 0||False;
5289 struct _SGEnv* sgenv;
5291 if (gWordTy != hWordTy) {
5292 /* We don't currently support this case. */
5293 VG_(tool_panic)("host/guest word size mismatch");
5296 /* Check we're not completely nuts */
5297 tl_assert(sizeof(UWord) == sizeof(void*));
5298 tl_assert(sizeof(Word) == sizeof(void*));
5299 tl_assert(sizeof(Addr) == sizeof(void*));
5300 tl_assert(sizeof(ULong) == 8);
5301 tl_assert(sizeof(Long) == 8);
5302 tl_assert(sizeof(Addr64) == 8);
5303 tl_assert(sizeof(UInt) == 4);
5304 tl_assert(sizeof(Int) == 4);
5306 /* Set up the running environment. Both .sb and .tmpMap are
5307 modified as we go along. Note that tmps are added to both
5308 .sb->tyenv and .tmpMap together, so the valid index-set for
5309 those two arrays should always be identical. */
5310 VG_(memset)(&pce, 0, sizeof(pce));
5311 pce.sb = deepCopyIRSBExceptStmts(sbIn);
5312 pce.trace = verboze;
5313 pce.hWordTy = hWordTy;
5314 pce.gWordTy = gWordTy;
5315 pce.guest_state_sizeB = layout->total_sizeB;
5317 pce.qmpMap = VG_(newXA)( VG_(malloc), "pc.h_instrument.1", VG_(free),
5318 sizeof(TempMapEnt));
5319 for (i = 0; i < sbIn->tyenv->types_used; i++) {
5322 ent.shadow = IRTemp_INVALID;
5323 VG_(addToXA)( pce.qmpMap, &ent );
5325 tl_assert( VG_(sizeXA)( pce.qmpMap ) == sbIn->tyenv->types_used );
5327 /* Also set up for the sg_ instrumenter. See comments at the top
5328 of this instrumentation section for details. The two parameters
5329 constitute a closure, which sg_ can use to correctly generate
5330 new IRTemps as needed. */
5331 sgenv = sg_instrument_init( for_sg__newIRTemp_cb,
5334 /* Stay sane. These two should agree! */
5335 tl_assert(layout->total_sizeB == PC_SIZEOF_GUEST_STATE);
5337 /* Copy verbatim any IR preamble preceding the first IMark */
5340 while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
5341 IRStmt* st = sbIn->stmts[i];
5343 tl_assert(isFlatIRStmt(st));
5344 stmt( 'C', &pce, sbIn->stmts[i] );
5348 /* Nasty problem. IR optimisation of the pre-instrumented IR may
5349 cause the IR following the preamble to contain references to IR
5350 temporaries defined in the preamble. Because the preamble isn't
5351 instrumented, these temporaries don't have any shadows.
5352 Nevertheless uses of them following the preamble will cause
5353 memcheck to generate references to their shadows. End effect is
5354 to cause IR sanity check failures, due to references to
5355 non-existent shadows. This is only evident for the complex
5356 preambles used for function wrapping on TOC-afflicted platforms
5357 (ppc64-linux, ppc32-aix5, ppc64-aix5).
5359 The following loop therefore scans the preamble looking for
5360 assignments to temporaries. For each one found it creates an
5361 assignment to the corresponding shadow temp, marking it as
5362 'defined'. This is the same resulting IR as if the main
5363 instrumentation loop before had been applied to the statement
5367 // FIXME: this isn't exactly right; only needs to generate shadows
5368 // for guest-word-typed temps
5369 for (j = 0; j < i; j++) {
5370 if (sbIn->stmts[j]->tag == Ist_WrTmp) {
5371 /* findShadowTmpV checks its arg is an original tmp;
5372 no need to assert that here. */
5373 IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp;
5374 IRTemp tmp_s = findShadowTmp(&pce, tmp_o);
5375 IRType ty_s = typeOfIRTemp(sbIn->tyenv, tmp_s);
5376 assign( 'V', &pce, tmp_s, definedOfType( ty_s ) );
5378 VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
5386 /* Iterate over the remaining stmts to generate instrumentation. */
5388 tl_assert(sbIn->stmts_used > 0);
5390 tl_assert(i < sbIn->stmts_used);
5391 tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
5393 for (/*use current i*/; i < sbIn->stmts_used; i++) {
5394 /* generate sg_ instrumentation for this stmt */
5395 sg_instrument_IRStmt( sgenv, pce.sb, sbIn->stmts[i],
5396 layout, gWordTy, hWordTy );
5397 /* generate h_ instrumentation for this stmt */
5398 schemeS( &pce, sbIn->stmts[i] );
5401 /* generate sg_ instrumentation for the final jump */
5402 sg_instrument_final_jump( sgenv, pce.sb, sbIn->next, sbIn->jumpkind,
5403 layout, gWordTy, hWordTy );
5405 /* and finalise .. */
5406 sg_instrument_fini( sgenv );
5408 /* If this fails, there's been some serious snafu with tmp management,
5409 that should be investigated. */
5410 tl_assert( VG_(sizeXA)( pce.qmpMap ) == pce.sb->tyenv->types_used );
5411 VG_(deleteXA)( pce.qmpMap );
5417 /*--------------------------------------------------------------------*/
5418 /*--- Initialisation ---*/
5419 /*--------------------------------------------------------------------*/
5421 void h_pre_clo_init ( void )
5423 // Other initialisation
5424 init_shadow_memory();
5428 void h_post_clo_init ( void )
5432 /*--------------------------------------------------------------------*/
5433 /*--- Finalisation ---*/
5434 /*--------------------------------------------------------------------*/
5436 void h_fini ( Int exitcode )
5438 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
5439 VG_(message)(Vg_UserMsg,
5440 "For counts of detected and suppressed errors, "
5441 "rerun with: -v\n");
5444 if (VG_(clo_stats)) {
5445 VG_(message)(Vg_DebugMsg,
5446 " h_: %'10llu client allocs, %'10llu client frees\n",
5447 stats__client_mallocs, stats__client_frees);
5448 VG_(message)(Vg_DebugMsg,
5449 " h_: %'10llu Segs allocd, %'10llu Segs recycled\n",
5450 stats__segs_allocd, stats__segs_recycled);
5454 if (h_clo_lossage_check) {
5455 VG_(message)(Vg_UserMsg, "\n");
5456 VG_(message)(Vg_UserMsg, "%12lld total memory references\n",
5457 stats__tot_mem_refs);
5458 VG_(message)(Vg_UserMsg, "%12lld of which are in a known segment\n",
5459 stats__refs_in_a_seg);
5460 VG_(message)(Vg_UserMsg, "%12lld of which are 'lost' w.r.t the seg\n",
5461 stats__refs_lost_seg);
5462 VG_(message)(Vg_UserMsg, "\n");
5464 VG_(message)(Vg_UserMsg, "\n");
5466 tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
5472 /*--------------------------------------------------------------------*/
5473 /*--- end h_main.c ---*/
5474 /*--------------------------------------------------------------------*/