blob: 9c71f3700c3f9018d9a490f115fce74e86e22639 [file] [log] [blame]
sewardj024598e2008-09-18 14:43:05 +00001
2/*--------------------------------------------------------------------*/
3/*--- Ptrcheck: a pointer-use checker. ---*/
4/*--- This file checks heap accesses. ---*/
5/*--- h_main.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
9 This file is part of Ptrcheck, a Valgrind tool for checking pointer
10 use in programs.
11
12 Initial version (Annelid):
13
14 Copyright (C) 2003-2008 Nicholas Nethercote
15 njn@valgrind.org
16
17 Valgrind-3.X port:
18
19 Copyright (C) 2008-2008 OpenWorks Ltd
20 info@open-works.co.uk
21
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.
26
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.
31
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
35 02111-1307, USA.
36
37 The GNU General Public License is contained in the file COPYING.
38*/
39
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
45
46// FIXME: should we shadow %RIP? Maybe not.
47
48// FIXME: shadows of temporaries created in preamble, a la memcheck?
49
50// FIXME: result of add_new_segment is always ignored
51
52// FIXME: the mechanism involving last_seg_added is really ugly.
53// Do something cleaner.
54
55// FIXME: post_reg_write_clientcall: check function pointer comparisons
56// are safe on toc-afflicted platforms
57
58// FIXME: tidy up findShadowTmp
59
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.
63
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.
67
68// FIXME: consider whether we could paint memory acquired from
69// sys_read etc as NONPTR rather than UNKNOWN.
70
71// XXX: recycle freed segments
72
73//--------------------------------------------------------------
74// Metadata:
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)
79//
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)
85//
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.
92//
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//--------------------------------------------------------------
103
104//--------------------------------------------------------------
105// Assumptions, etc:
106// - see comment at top of SK_(instrument)() for how sub-word ops are
107// handled.
108//
109// - ioctl(), socketcall() (and ipc() will be) assumed to return non-pointers
110//
111// - FPU_W is assumed to never write pointers.
112//
113// - Assuming none of the post_mem_writes create segments worth tracking.
114//
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//--------------------------------------------------------------
120
121//--------------------------------------------------------------
122// What I am checking:
123// - Type errors:
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.
130//
131// - LOAD, STORE:
132// * ptr.vseg must match ptee.aseg.
133// * ptee.aseg must not be a freed segment.
134//
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.
138//
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.
143//
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.)
148//
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.
152//
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.
155//
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.
162//
163// - PUTF: input should be non-pointer
164//
165// - arithmetic error messages: eg. for adding two pointers, just giving the
166// segments, not the actual pointers.
167//
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.
171//
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
176// there).
177//
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
183// no loss, really.
184//
185// Other:
186// - not doing anything with mprotect(); probably not worth the effort.
187//--------------------------------------------------------------
188
189//--------------------------------------------------------------
190// Todo:
191// - Segments for stack frames. Would detect (some, large) stack
192// over/under-runs, dangling pointers.
193//
194// - Segments for static data. Would detect over/under-runs. Requires
195// reading debug info.
196//--------------------------------------------------------------
197
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
206// ...
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//--------------------------------------------------------------
211
212//#include "vg_skin.h"
213
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"
235
236#include "pc_common.h"
237
238//#include "h_list.h"
239#include "h_main.h"
240
241#include "sg_main.h" // sg_instrument_*, and struct _SGEnv
242
243
244
245/*------------------------------------------------------------*/
246/*--- Debug/trace options ---*/
247/*------------------------------------------------------------*/
248
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. */
252#define SC_SEGS 0
253
254static ULong stats__client_mallocs = 0;
255static ULong stats__client_frees = 0;
256static ULong stats__segs_allocd = 0;
257static ULong stats__segs_recycled = 0;
sewardj024598e2008-09-18 14:43:05 +0000258
259
260//////////////////////////////////////////////////////////////
261// //
262// Segments low level storage //
263// //
264//////////////////////////////////////////////////////////////
265
266// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since
267// pc_common.c needs to see them, for error processing
268
269// we only start recycling segs when this many exist
270#define N_FREED_SEGS (1 * 1000 * 1000)
271
272struct _Seg {
273 Addr addr;
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;
280};
281
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.
284void Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n)
285{
286 if (a < seg->addr) {
287 *cmp = -1;
288 *n = seg->addr - a;
289 } else if (a < seg->addr + seg->szB && seg->szB > 0) {
290 *cmp = 0;
291 *n = a - seg->addr;
292 } else {
293 *cmp = 1;
294 *n = a - (seg->addr + seg->szB);
295 }
296}
297
298inline Bool Seg__is_freed(Seg* seg)
299{
300 if (!is_known_segment(seg))
301 return False;
302 else
303 return seg->nextfree != (Seg*)1;
304}
305
306ExeContext* Seg__where(Seg* seg)
307{
308 tl_assert(is_known_segment(seg));
309 return seg->ec;
310}
311
312SizeT Seg__size(Seg* seg)
313{
314 tl_assert(is_known_segment(seg));
315 return seg->szB;
316}
317
318Addr Seg__addr(Seg* seg)
319{
320 tl_assert(is_known_segment(seg));
321 return seg->addr;
322}
323
324
325#define N_SEGS_PER_GROUP 10000
326
327typedef
328 struct _SegGroup {
329 struct _SegGroup* admin;
330 UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */
331 Seg segs[N_SEGS_PER_GROUP];
332 }
333 SegGroup;
334
335static SegGroup* group_list = NULL;
336static UWord nFreeSegs = 0;
337static Seg* freesegs_youngest = NULL;
338static Seg* freesegs_oldest = NULL;
339
340
341static SegGroup* new_SegGroup ( void ) {
342 SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup));
343 VG_(memset)(g, 0, sizeof(*g));
344 return g;
345}
346
347/* Get a completely new Seg */
348static Seg* new_Seg ( void )
349{
350 Seg* teg;
351 SegGroup* g;
352 if (group_list == NULL) {
353 g = new_SegGroup();
354 g->admin = NULL;
355 group_list = g;
356 }
357 tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP);
358 if (group_list->nextfree == N_SEGS_PER_GROUP) {
359 g = new_SegGroup();
360 g->admin = group_list;
361 group_list = g;
362 }
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++;
367 return teg;
368}
369
370static Seg* get_Seg_for_malloc ( void )
371{
372 Seg* seg;
373 if (nFreeSegs < N_FREED_SEGS) {
374 seg = new_Seg();
375 seg->nextfree = (Seg*)1;
376 return seg;
377 }
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;
384 nFreeSegs--;
385 seg->nextfree = (Seg*)1;
386 stats__segs_recycled++;
387 return seg;
388}
389
390static void set_Seg_freed ( Seg* seg )
391{
392 tl_assert(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;
400 nFreeSegs++;
401 } else {
402 tl_assert(freesegs_youngest);
403 tl_assert(freesegs_oldest);
404 if (nFreeSegs == 1) {
405 tl_assert(freesegs_youngest == freesegs_oldest);
406 } else {
407 tl_assert(freesegs_youngest != freesegs_oldest);
408 }
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;
414 nFreeSegs++;
415 }
416}
417
sewardj95208452008-10-18 19:55:31 +0000418static WordFM* addr_to_seg_map = NULL; /* GuestAddr -> Seg* */
sewardj024598e2008-09-18 14:43:05 +0000419
420static void addr_to_seg_map_ENSURE_INIT ( void )
421{
422 if (UNLIKELY(addr_to_seg_map == NULL)) {
423 addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1",
sewardj95208452008-10-18 19:55:31 +0000424 VG_(free), NULL/*unboxedcmp*/ );
sewardj024598e2008-09-18 14:43:05 +0000425 }
426}
427
428static Seg* find_Seg_by_addr ( Addr ga )
429{
430 UWord keyW, valW;
431 addr_to_seg_map_ENSURE_INIT();
432 if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) {
433 tl_assert(keyW == ga);
434 return (Seg*)valW;
435 } else {
436 return NULL;
437 }
438}
439
440static void bind_addr_to_Seg ( Addr ga, Seg* seg )
441{
442 Bool b;
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 */
446}
447
448static void unbind_addr_from_Seg ( Addr ga )
449{
450 Bool b;
451 UWord keyW, valW;
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);
457}
458
459
460//////////////////////////////////////////////////////////////
461//////////////////////////////////////////////////////////////
462//////////////////////////////////////////////////////////////
463
464// So that post_reg_write_clientcall knows the segment just allocated.
465static Seg* last_seg_added = NULL;
466
467// Returns the added heap segment
468static Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size )
469{
470 Seg* seg = get_Seg_for_malloc();
471 tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */
472 seg->addr = p;
473 seg->szB = size;
474 seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
475 tl_assert(!Seg__is_freed(seg));
476
477 bind_addr_to_Seg(p, seg);
478
479 last_seg_added = seg;
480
481 return seg;
482}
483
484// Forward declarations
485static void copy_mem( Addr from, Addr to, SizeT len );
486static void set_mem_unknown ( Addr a, SizeT len );
487
488static inline VG_REGPARM(1) Seg* nonptr_or_unknown(UWord x); /*fwds*/
489
490static
491void* alloc_and_new_mem_heap ( ThreadId tid,
492 SizeT size, SizeT alignment, Bool is_zeroed )
493{
494 Addr p;
495
496 if ( ((SSizeT)size) < 0) return NULL;
497
498 p = (Addr)VG_(cli_malloc)(alignment, size);
499 if (is_zeroed) VG_(memset)((void*)p, 0, size);
500
501 set_mem_unknown( p, size );
502 add_new_segment( tid, p, size );
503
504 stats__client_mallocs++;
505 return (void*)p;
506}
507
508static void die_and_free_mem_heap ( ThreadId tid, Seg* seg )
509{
510 // Empty and free the actual block
511 tl_assert(!Seg__is_freed(seg));
512 set_mem_unknown( seg->addr, seg->szB );
513
514 VG_(cli_free)( (void*)seg->addr );
515
516 // Remember where freed
517 seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
518
519 set_Seg_freed(seg);
520 unbind_addr_from_Seg( seg->addr );
521
522 stats__client_frees++;
523}
524
525static void handle_free_heap( ThreadId tid, void* p )
526{
527 Seg* seg = find_Seg_by_addr( (Addr)p );
528 if (!seg) {
529 /* freeing a block that wasn't malloc'd. Ignore. */
530 return;
531 }
532 die_and_free_mem_heap( tid, seg );
533}
534
535
536/*------------------------------------------------------------*/
537/*--- Shadow memory ---*/
538/*------------------------------------------------------------*/
539
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.
546
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. */
550
551#if 0
552__attribute__((unused))
553static void pp_curr_ExeContext(void)
554{
555 VG_(pp_ExeContext)(
556 VG_(get_ExeContext)(
557 VG_(get_current_or_recent_tid)() ) );
558 VG_(message)(Vg_UserMsg, "");
559}
560#endif
561
562#if defined(VGA_x86) || defined(VGA_ppc32)
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 */
572#else
573# error "Unknown arch"
574#endif
575
576typedef
577 struct {
578 Seg* vseg[SEC_MAP_WORDS];
579 }
580 SecMap;
581
582static SecMap distinguished_secondary_map;
583
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
588 lookups.
589*/
590typedef
591 struct {
592 Addr base;
593 SecMap* sm;
594 }
595 PriMapEnt;
596
597/* Primary map is an OSet of PriMapEnt (primap_L2), "fronted" by a
598 cache (primap_L1). */
599
600/* Tunable parameter: How big is the L1 queue? */
601#define N_PRIMAP_L1 24
602
603/* Tunable parameter: How far along the L1 queue to insert
604 entries resulting from L2 lookups? */
605#define PRIMAP_L1_INSERT_IX 12
606
607static struct {
608 Addr base; // must be 64k aligned
609 PriMapEnt* ent; // pointer to the matching primap_L2 node
610 }
611 primap_L1[N_PRIMAP_L1];
612
613static OSet* primap_L2 = NULL;
614
615
616/* # searches initiated in auxmap_L1, and # base cmps required */
617static ULong n_primap_L1_searches = 0;
618static 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. */
621static ULong n_primap_L2_searches = 0;
622static ULong n_primap_L2_nodes = 0;
623
624
625static void init_shadow_memory ( void )
626{
627 Int i;
628
629 for (i = 0; i < SEC_MAP_WORDS; i++)
630 distinguished_secondary_map.vseg[i] = NONPTR;
631
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;
636 }
637
638 tl_assert(0 == offsetof(PriMapEnt,base));
639 tl_assert(sizeof(Addr) == sizeof(void*));
640 primap_L2 = VG_(OSetGen_Create)( /*keyOff*/ offsetof(PriMapEnt,base),
641 /*fastCmp*/ NULL,
642 VG_(malloc), "pc.h_main.ism.1",
643 VG_(free) );
644 tl_assert(primap_L2);
645}
646
647static void insert_into_primap_L1_at ( Word rank, PriMapEnt* ent )
648{
649 Word i;
650 tl_assert(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;
656}
657
658static inline PriMapEnt* maybe_find_in_primap ( Addr a )
659{
660 PriMapEnt key;
661 PriMapEnt* res;
662 Word i;
663
664 a &= ~(Addr)0xFFFF;
665
666 /* First search the front-cache, which is a self-organising
667 list containing the most popular entries. */
668
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;
679 }
680
681 n_primap_L1_searches++;
682
683 for (i = 0; i < N_PRIMAP_L1; i++) {
684 if (primap_L1[i].base == a) {
685 break;
686 }
687 }
688 tl_assert(i >= 0 && i <= N_PRIMAP_L1);
689
690 n_primap_L1_cmps += (ULong)(i+1);
691
692 if (i < N_PRIMAP_L1) {
693 if (i > 0) {
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;
700 i--;
701 }
702 return primap_L1[i].ent;
703 }
704
705 n_primap_L2_searches++;
706
707 /* First see if we already have it. */
708 key.base = a;
709 key.sm = 0;
710
711 res = VG_(OSetGen_Lookup)(primap_L2, &key);
712 if (res)
713 insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, res );
714 return res;
715}
716
717static SecMap* alloc_secondary_map ( void )
718{
719 SecMap* map;
720 UInt i;
721
722 // JRS 2008-June-25: what's the following assertion for?
723 tl_assert(0 == (sizeof(SecMap) % VKI_MAX_PAGE_SIZE));
724
725 map = VG_(am_shadow_alloc)( sizeof(SecMap) );
726 if (map == NULL)
727 VG_(out_of_memory_NORETURN)( "annelid:allocate new SecMap",
728 sizeof(SecMap) );
729
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);
733 return map;
734}
735
736static PriMapEnt* find_or_alloc_in_primap ( Addr a )
737{
738 PriMapEnt *nyu, *res;
739
740 /* First see if we already have it. */
741 res = maybe_find_in_primap( a );
742 if (LIKELY(res))
743 return res;
744
745 /* Ok, there's no entry in the secondary map, so we'll have
746 to allocate one. */
747 a &= ~(Addr)0xFFFF;
748
749 nyu = (PriMapEnt*) VG_(OSetGen_AllocNode)(
750 primap_L2, sizeof(PriMapEnt) );
751 tl_assert(nyu);
752 nyu->base = a;
753 nyu->sm = alloc_secondary_map();
754 tl_assert(nyu->sm);
755 VG_(OSetGen_Insert)( primap_L2, nyu );
756 insert_into_primap_L1_at( PRIMAP_L1_INSERT_IX, nyu );
757 n_primap_L2_nodes++;
758 return nyu;
759}
760
761/////////////////////////////////////////////////
762
763// Nb: 'a' must be naturally word aligned for the host.
764static inline Seg* get_mem_vseg ( Addr a )
765{
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];
770}
771
772// Nb: 'a' must be naturally word aligned for the host.
773static inline void set_mem_vseg ( Addr a, Seg* vseg )
774{
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;
779}
780
sewardj95208452008-10-18 19:55:31 +0000781// Find the Seg which contains the given address.
sewardj024598e2008-09-18 14:43:05 +0000782// Returns UNKNOWN if no matches. Never returns BOTTOM or NONPTR.
783// Also, only returns in-use segments, not freed ones.
sewardj95208452008-10-18 19:55:31 +0000784/* 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'.
787
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
790 and easy).
791
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.
799*/
800static Seg* get_Seg_containing_addr( Addr a )
801{
802 UWord keyW, valW;
803 Seg* s2;
804
805 /* Since we are going to poke around in it */
806 addr_to_seg_map_ENSURE_INIT();
807
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);
813 s2 = (Seg*)valW;
814 tl_assert(s2->addr == a);
815 } else {
816 Bool ok;
817 UWord kMin, vMin, kMax, vMax;
818 Seg minSeg;
819 Seg maxSeg;
820 UWord minAddr = 0;
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
838 Seg itself. */
839 s2 = (Seg*)vMin;
840 tl_assert(kMin == s2->addr);
841 if (s2 == &minSeg) {
842 /* the former */
843 s2 = UNKNOWN;
844 } else {
845 /* the latter */
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 */)
850 s2 = UNKNOWN;
851 }
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
855 greater than a. */
856 tl_assert(kMax == ((Seg*)vMax)->addr);
857 if (kMax == (UWord)&maxSeg) {
858 /* nothing we can check */
859 } else {
860 tl_assert(a < kMax); /* hence also a < ((Seg*)vMax)->addr */
861 }
862 }
863
864 return s2;
865}
866
867/* XXXX very slow reference implementation. Do not use.
sewardj024598e2008-09-18 14:43:05 +0000868static Seg* get_Seg_containing_addr_SLOW( Addr a )
869{
870 SegGroup* group;
871 UWord i;
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]))
877 continue;
878 if (group->segs[i].addr <= a
879 && a < group->segs[i].addr + group->segs[i].szB)
880 return &group->segs[i];
881 }
882 }
883 return UNKNOWN;
884}
sewardj95208452008-10-18 19:55:31 +0000885*/
886
sewardj024598e2008-09-18 14:43:05 +0000887
888
889/*------------------------------------------------------------*/
890/*--- malloc() et al replacements ---*/
891/*------------------------------------------------------------*/
892
893void* h_replace_malloc ( ThreadId tid, SizeT n )
894{
895 return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
896 /*is_zeroed*/False );
897}
898
899void* h_replace___builtin_new ( ThreadId tid, SizeT n )
900{
901 return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
902 /*is_zeroed*/False );
903}
904
905void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
906{
907 return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
908 /*is_zeroed*/False );
909}
910
911void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
912{
913 return alloc_and_new_mem_heap ( tid, n, align,
914 /*is_zeroed*/False );
915}
916
917void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
918{
919 return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
920 /*is_zeroed*/True );
921}
922
923void h_replace_free ( ThreadId tid, void* p )
924{
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.
931 //
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.
937
938 handle_free_heap(tid, p);
939}
940
941void h_replace___builtin_delete ( ThreadId tid, void* p )
942{
943 handle_free_heap(tid, p);
944}
945
946void h_replace___builtin_vec_delete ( ThreadId tid, void* p )
947{
948 handle_free_heap(tid, p);
949}
950
951void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
952{
953 Seg* seg;
954
955 /* First try and find the block. */
956 seg = find_Seg_by_addr( (Addr)p_old );
957 if (!seg)
958 return NULL;
959
960 tl_assert(seg->addr == (Addr)p_old);
961
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);
966
967 /* Notification: copy retained part */
968 copy_mem ( (Addr)p_old, p_new, new_size );
969
970 /* Free old memory */
971 die_and_free_mem_heap( tid, seg );
972
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 );
977
978 return (void*)p_new;
979 } else {
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);
983
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 );
987
988 /* Free old memory */
989 die_and_free_mem_heap( tid, seg );
990
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 );
997
998 return (void*)p_new;
999 }
1000}
1001
1002
1003/*------------------------------------------------------------*/
1004/*--- Memory events ---*/
1005/*------------------------------------------------------------*/
1006
1007static inline
1008void set_mem ( Addr a, SizeT len, Seg* seg )
1009{
1010 Addr end;
1011
1012 if (0 == len)
1013 return;
1014
1015 if (len > 100 * 1000 * 1000)
1016 VG_(message)(Vg_UserMsg,
1017 "Warning: set address range state: large range %lu", len);
1018
1019 a = VG_ROUNDDN(a, sizeof(UWord));
1020 end = VG_ROUNDUP(a + len, sizeof(UWord));
1021 for ( ; a < end; a += sizeof(UWord))
1022 set_mem_vseg(a, seg);
1023}
1024
1025static void set_mem_unknown( Addr a, SizeT len )
1026{
1027 set_mem( a, len, UNKNOWN );
1028}
1029
1030//zz static void set_mem_nonptr( Addr a, UInt len )
1031//zz {
1032//zz set_mem( a, len, NONPTR );
1033//zz }
1034
1035void h_new_mem_startup( Addr a, SizeT len,
1036 Bool rr, Bool ww, Bool xx, ULong di_handle )
1037{
1038 if (0) VG_(printf)("new_mem_startup(%#lx,%lu)\n", a, len);
1039 set_mem_unknown( a, len );
1040 //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1041}
1042
1043//zz // XXX: Currently not doing anything with brk() -- new segments, or not?
1044//zz // Proper way to do it would be to grow/shrink a single, special brk segment.
1045//zz //
1046//zz // brk is difficult: it defines a single segment, of changeable size.
1047//zz // It starts off with size zero, at the address given by brk(0). There are
1048//zz // no pointers within the program to it. Any subsequent calls by the
1049//zz // program to brk() (possibly growing or shrinking it) return pointers to
1050//zz // the *end* of the segment (nb: this is the kernel brk(), which is
1051//zz // different to the libc brk()).
1052//zz //
1053//zz // If fixing this, don't forget to update the brk case in SK_(post_syscall).
1054//zz //
1055//zz // Nb: not sure if the return value is the last byte addressible, or one
1056//zz // past the end of the segment.
1057//zz //
1058//zz static void new_mem_brk( Addr a, UInt len )
1059//zz {
1060//zz set_mem_unknown(a, len);
1061//zz //VG_(skin_panic)("can't handle new_mem_brk");
1062//zz }
1063
1064// Not quite right: if you mmap a segment into a specified place, it could
1065// be legitimate to do certain arithmetic with the pointer that it wouldn't
1066// otherwise. Hopefully this is rare, though.
1067void h_new_mem_mmap( Addr a, SizeT len,
1068 Bool rr, Bool ww, Bool xx, ULong di_handle )
1069{
1070 if (0) VG_(printf)("new_mem_mmap(%#lx,%lu)\n", a, len);
1071//zz #if 0
1072//zz Seg seg = NULL;
1073//zz
1074//zz // Check for overlapping segments
1075//zz #if 0
1076//zz is_overlapping_seg___a = a; // 'free' variable
1077//zz is_overlapping_seg___len = len; // 'free' variable
1078//zz seg = (Seg)VG_(HT_first_match) ( mlist, is_overlapping_seg );
1079//zz is_overlapping_seg___a = 0; // paranoia, reset
1080//zz is_overlapping_seg___len = 0; // paranoia, reset
1081//zz #endif
1082//zz
1083//zz // XXX: do this check properly with ISLists
1084//zz
1085//zz if ( ISList__findI( seglist, a, &seg )) {
1086//zz sk_assert(SegMmap == seg->status || SegMmapFree == seg->status);
1087//zz if (SegMmap == seg->status)
1088//zz
1089//zz }
1090//zz
1091//zz if (NULL != seg) {
1092//zz // Right, we found an overlap
1093//zz if (VG_(clo_verbosity) > 1)
1094//zz VG_(message)(Vg_UserMsg, "mmap overlap: old: %#lx, %d; new: %#lx, %d",
1095//zz seg->left, Seg__size(seg), a, len);
1096//zz if (seg->left <= a && a <= seg->right) {
1097//zz // New one truncates end of the old one. Nb: we don't adjust its
1098//zz // size, because the first segment's pointer can be (and for
1099//zz // Konqueror, is) legitimately used to access parts of the second
1100//zz // segment. At least, I assume Konqueror is doing something legal.
1101//zz // so that a size mismatch upon munmap isn't a problem.
1102//zz // seg->size = a - seg->data;
1103//zz // seg->is_truncated_map = True;
1104//zz // if (VG_(clo_verbosity) > 1)
1105//zz // VG_(message)(Vg_UserMsg, "old seg truncated to length %d",
1106//zz // seg->size);
1107//zz } else {
1108//zz VG_(skin_panic)("Can't handle this mmap() overlap case");
1109//zz }
1110//zz }
1111 set_mem_unknown( a, len );
1112 //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1113//zz #endif
1114}
1115
1116static void copy_mem( Addr from, Addr to, SizeT len )
1117{
1118 Addr fromend = from + len;
1119
1120 // Must be aligned due to malloc always returning aligned objects.
1121 tl_assert(VG_IS_8_ALIGNED(from) && VG_IS_8_ALIGNED(to));
1122
1123 // Must only be called with positive len.
1124 if (0 == len)
1125 return;
1126
1127 for ( ; from < fromend; from += sizeof(UWord), to += sizeof(UWord))
1128 set_mem_vseg( to, get_mem_vseg(from) );
1129}
1130
1131//zz // Similar to SK_(realloc)()
1132//zz static void copy_mem_remap( Addr from, Addr to, UInt len )
1133//zz {
1134//zz VG_(skin_panic)("argh: copy_mem_remap");
1135//zz }
1136//zz
1137//zz static void die_mem_brk( Addr a, UInt len )
1138//zz {
1139//zz set_mem_unknown(a, len);
1140//zz // VG_(skin_panic)("can't handle die_mem_brk()");
1141//zz }
1142
1143void h_die_mem_munmap( Addr a, SizeT len )
1144{
1145// handle_free_munmap( (void*)a, len );
1146}
1147
1148// Don't need to check all addresses within the block; in the absence of
1149// discontiguous segments, the segments for the first and last bytes should
1150// be the same. Can't easily check the pointer segment matches the block
1151// segment, unfortunately, but the first/last check should catch most
1152// errors.
1153static void pre_mem_access2 ( CorePart part, ThreadId tid, Char* str,
1154 Addr s/*tart*/, Addr e/*nd*/ )
1155{
1156 Seg *seglo, *seghi;
1157 Bool s_in_seglo, s_in_seghi, e_in_seglo, e_in_seghi;
1158
1159 // Don't check code being translated -- very slow, and not much point
1160 if (Vg_CoreTranslate == part) return;
1161
1162 // Don't check the signal case -- only happens in core, no need to check
1163 if (Vg_CoreSignal == part) return;
1164
1165 // Only expect syscalls after this point
1166 if (part != Vg_CoreSysCall) {
1167 VG_(printf)("part = %d\n", part);
1168 VG_(tool_panic)("unknown corepart in pre_mem_access2");
1169 }
1170
1171 // Check first and last bytes match
sewardj95208452008-10-18 19:55:31 +00001172 seglo = get_Seg_containing_addr( s );
1173 seghi = get_Seg_containing_addr( e );
sewardj024598e2008-09-18 14:43:05 +00001174 tl_assert( BOTTOM != seglo && NONPTR != seglo );
1175 tl_assert( BOTTOM != seghi && NONPTR != seghi );
1176
1177 /* so seglo and seghi are either UNKNOWN or P(..) */
1178 s_in_seglo
1179 = is_known_segment(seglo)
1180 && seglo->addr <= s && s < seglo->addr + seglo->szB;
1181 s_in_seghi
1182 = is_known_segment(seghi)
1183 && seghi->addr <= s && s < seghi->addr + seghi->szB;
1184 e_in_seglo
1185 = is_known_segment(seglo)
1186 && seglo->addr <= e && e < seglo->addr + seglo->szB;
1187 e_in_seghi
1188 = is_known_segment(seghi)
1189 && seghi->addr <= e && e < seghi->addr + seghi->szB;
1190
1191 /* record an error if start and end are in different, but known
1192 segments */
1193 if (is_known_segment(seglo) && is_known_segment(seghi)
1194 && seglo != seghi) {
1195 h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
1196 }
1197 else
1198 /* record an error if start is in a known segment but end isn't */
1199 if (is_known_segment(seglo) && !is_known_segment(seghi)) {
1200 h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
1201 }
1202 else
1203 /* record an error if end is in a known segment but start isn't */
1204 if (!is_known_segment(seglo) && is_known_segment(seghi)) {
1205 h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi);
1206 }
1207}
1208
1209void h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
1210 Addr base, SizeT size )
1211{
1212 pre_mem_access2( part, tid, s, base, base + size - 1 );
1213}
1214
1215void h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
1216 Char* s, Addr lo )
1217{
1218 Addr hi = lo;
1219
1220 // Nb: the '\0' must be included in the lo...hi range
1221 while ('\0' != *(Char*)hi) hi++;
1222 pre_mem_access2( part, tid, s, lo, hi );
1223}
1224
1225//zz static void post_mem_write(Addr a, UInt len)
1226//zz {
1227//zz set_mem_unknown(a, len);
1228//zz }
1229
1230
1231/*------------------------------------------------------------*/
1232/*--- Register event handlers ---*/
1233/*------------------------------------------------------------*/
1234
1235//zz static void post_regs_write_init ( void )
1236//zz {
1237//zz UInt i;
1238//zz for (i = R_EAX; i <= R_EDI; i++)
1239//zz VG_(set_shadow_archreg)( i, (UInt)UNKNOWN );
1240//zz
1241//zz // Don't bother about eflags
1242//zz }
1243
1244// BEGIN move this uglyness to pc_machine.c
1245
1246static inline Bool host_is_big_endian ( void ) {
1247 UInt x = 0x11223344;
1248 return 0x1122 == *(UShort*)(&x);
1249}
1250static inline Bool host_is_little_endian ( void ) {
1251 UInt x = 0x11223344;
1252 return 0x3344 == *(UShort*)(&x);
1253}
1254
1255#define N_INTREGINFO_OFFSETS 4
1256
1257/* Holds the result of a query to 'get_IntRegInfo'. Valid values for
1258 n_offsets are:
1259
1260 -1: means the queried guest state slice exactly matches
1261 one integer register
1262
1263 0: means the queried guest state slice does not overlap any
1264 integer registers
1265
1266 1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset
1267 overlaps n_offsets different integer registers, and their base
1268 offsets are placed in the offsets array.
1269*/
1270typedef
1271 struct {
1272 Int offsets[N_INTREGINFO_OFFSETS];
1273 Int n_offsets;
1274 }
1275 IntRegInfo;
1276
1277
1278#if defined(VGA_x86)
1279# include "libvex_guest_x86.h"
1280# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State)
1281#endif
1282
1283#if defined(VGA_amd64)
1284# include "libvex_guest_amd64.h"
1285# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State)
1286# define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO)
1287# define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO)
1288#endif
1289
1290#if defined(VGA_ppc32)
1291# include "libvex_guest_ppc32.h"
1292# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State)
1293#endif
1294
1295#if defined(VGA_ppc64)
1296# include "libvex_guest_ppc64.h"
1297# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
1298#endif
1299
1300
1301/* See description on definition of type IntRegInfo. */
1302static void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
1303{
1304 /* --------------------- x86 --------------------- */
1305
1306# if defined(VGA_x86)
1307
1308# define GOF(_fieldname) \
1309 (offsetof(VexGuestX86State,guest_##_fieldname))
1310
1311 Int o = offset;
1312 Int sz = szB;
1313 Bool is4 = sz == 4;
1314 Bool is21 = sz == 2 || sz == 1;
1315
1316 tl_assert(sz > 0);
1317 tl_assert(host_is_little_endian());
1318
1319 /* Set default state to "does not intersect any int register". */
1320 VG_(memset)( iii, 0, sizeof(*iii) );
1321
1322 /* Exact accesses to integer registers */
1323 if (o == GOF(EAX) && is4) goto exactly1;
1324 if (o == GOF(ECX) && is4) goto exactly1;
1325 if (o == GOF(EDX) && is4) goto exactly1;
1326 if (o == GOF(EBX) && is4) goto exactly1;
1327 if (o == GOF(ESP) && is4) goto exactly1;
1328 if (o == GOF(EBP) && is4) goto exactly1;
1329 if (o == GOF(ESI) && is4) goto exactly1;
1330 if (o == GOF(EDI) && is4) goto exactly1;
1331 if (o == GOF(EIP) && 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;
1339
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; }
sewardjdb440982008-10-11 10:18:16 +00001346 if (o == GOF(EBX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
sewardj024598e2008-09-18 14:43:05 +00001347 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; }
1351
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;
1356
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;
1364
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;
1374
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;
1378
1379 /* the entire mmx/x87 register bank in one big piece */
1380 if (o == GOF(FPREG) && sz == 64) goto none;
1381
1382 VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz);
1383 tl_assert(0);
1384# undef GOF
1385
1386 /* -------------------- amd64 -------------------- */
1387
1388# elif defined(VGA_amd64)
1389
1390# define GOF(_fieldname) \
1391 (offsetof(VexGuestAMD64State,guest_##_fieldname))
1392
1393 Int o = offset;
1394 Int sz = szB;
1395 Bool is421 = sz == 4 || sz == 2 || sz == 1;
1396 Bool is8 = sz == 8;
1397
1398 tl_assert(sz > 0);
1399 tl_assert(host_is_little_endian());
1400
1401 /* Set default state to "does not intersect any int register". */
1402 VG_(memset)( iii, 0, sizeof(*iii) );
1403
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(CC_OP) && is8) goto none;
1423 if (o == GOF(CC_DEP1) && is8) goto none;
1424 if (o == GOF(CC_DEP2) && is8) goto none;
1425 if (o == GOF(CC_NDEP) && is8) goto none;
1426 if (o == GOF(DFLAG) && is8) goto none;
1427 if (o == GOF(IDFLAG) && is8) goto none;
1428
1429 /* Partial accesses to integer registers */
1430 if (o == GOF(RAX) && is421) { o -= 0; goto contains_o; }
1431 if (o == GOF(RAX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1432 if (o == GOF(RCX) && is421) { o -= 0; goto contains_o; }
1433 if (o == GOF(RCX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1434 if (o == GOF(RDX) && is421) { o -= 0; goto contains_o; }
1435 if (o == GOF(RDX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1436 if (o == GOF(RBX) && is421) { o -= 0; goto contains_o; }
1437 if (o == GOF(RBX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1438 if (o == GOF(RBP) && is421) { o -= 0; goto contains_o; }
1439 if (o == GOF(RSI) && is421) { o -= 0; goto contains_o; }
1440 if (o == GOF(RDI) && is421) { o -= 0; goto contains_o; }
1441 if (o == GOF(R8) && is421) { o -= 0; goto contains_o; }
1442 if (o == GOF(R9) && is421) { o -= 0; goto contains_o; }
1443 if (o == GOF(R10) && is421) { o -= 0; goto contains_o; }
1444 if (o == GOF(R11) && is421) { o -= 0; goto contains_o; }
1445 if (o == GOF(R12) && is421) { o -= 0; goto contains_o; }
1446 if (o == GOF(R13) && is421) { o -= 0; goto contains_o; }
1447 if (o == GOF(R14) && is421) { o -= 0; goto contains_o; }
1448 if (o == GOF(R15) && is421) { o -= 0; goto contains_o; }
1449
1450 /* Segment related guff */
1451 if (o == GOF(FS_ZERO) && is8) goto exactly1;
1452
1453 /* FP admin related */
1454 if (o == GOF(SSEROUND) && is8) goto none;
1455 if (o == GOF(FPROUND) && is8) goto none;
1456 if (o == GOF(EMWARN) && sz == 4) goto none;
1457 if (o == GOF(FTOP) && sz == 4) goto none;
1458 if (o == GOF(FPTAG) && is8) goto none;
1459 if (o == GOF(FC3210) && is8) goto none;
1460
1461 /* xmm registers, including arbitrary sub-parts */
1462 if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1463 if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1464 if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1465 if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1466 if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1467 if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1468 if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1469 if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1470 if (o >= GOF(XMM8) && o+sz <= GOF(XMM8)+16) goto none;
1471 if (o >= GOF(XMM9) && o+sz <= GOF(XMM9)+16) goto none;
1472 if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none;
1473 if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none;
1474 if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none;
1475 if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none;
1476 if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none;
1477 if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none;
1478
1479 /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1480 to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1481 if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1482
1483 VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz);
1484 tl_assert(0);
1485# undef GOF
1486
1487 /* -------------------- ppc32 -------------------- */
1488
1489# elif defined(VGA_ppc32)
1490
1491# define GOF(_fieldname) \
1492 (offsetof(VexGuestPPC32State,guest_##_fieldname))
1493
1494 Int o = offset;
1495 Int sz = szB;
1496 Bool is4 = sz == 4;
1497 Bool is8 = sz == 8;
1498
1499 tl_assert(sz > 0);
1500 tl_assert(host_is_big_endian());
1501
1502 /* Set default state to "does not intersect any int register". */
1503 VG_(memset)( iii, 0, sizeof(*iii) );
1504
1505 /* Exact accesses to integer registers */
1506 if (o == GOF(GPR0) && is4) goto exactly1;
1507 if (o == GOF(GPR1) && is4) goto exactly1;
1508 if (o == GOF(GPR2) && is4) goto exactly1;
1509 if (o == GOF(GPR3) && is4) goto exactly1;
1510 if (o == GOF(GPR4) && is4) goto exactly1;
1511 if (o == GOF(GPR5) && is4) goto exactly1;
1512 if (o == GOF(GPR6) && is4) goto exactly1;
1513 if (o == GOF(GPR7) && is4) goto exactly1;
1514 if (o == GOF(GPR8) && is4) goto exactly1;
1515 if (o == GOF(GPR9) && is4) goto exactly1;
1516 if (o == GOF(GPR10) && is4) goto exactly1;
1517 if (o == GOF(GPR11) && is4) goto exactly1;
1518 if (o == GOF(GPR12) && is4) goto exactly1;
1519 if (o == GOF(GPR13) && is4) goto exactly1;
1520 if (o == GOF(GPR14) && is4) goto exactly1;
1521 if (o == GOF(GPR15) && is4) goto exactly1;
1522 if (o == GOF(GPR16) && is4) goto exactly1;
1523 if (o == GOF(GPR17) && is4) goto exactly1;
1524 if (o == GOF(GPR18) && is4) goto exactly1;
1525 if (o == GOF(GPR19) && is4) goto exactly1;
1526 if (o == GOF(GPR20) && is4) goto exactly1;
1527 if (o == GOF(GPR21) && is4) goto exactly1;
1528 if (o == GOF(GPR22) && is4) goto exactly1;
1529 if (o == GOF(GPR23) && is4) goto exactly1;
1530 if (o == GOF(GPR24) && is4) goto exactly1;
1531 if (o == GOF(GPR25) && is4) goto exactly1;
1532 if (o == GOF(GPR26) && is4) goto exactly1;
1533 if (o == GOF(GPR27) && is4) goto exactly1;
1534 if (o == GOF(GPR28) && is4) goto exactly1;
1535 if (o == GOF(GPR29) && is4) goto exactly1;
1536 if (o == GOF(GPR30) && is4) goto exactly1;
1537 if (o == GOF(GPR31) && is4) goto exactly1;
1538
1539 /* Misc integer reg and condition code accesses */
1540 if (o == GOF(LR) && is4) goto exactly1;
1541 if (o == GOF(CTR) && is4) goto exactly1;
1542 if (o == GOF(CIA) && is4) goto none;
1543 if (o == GOF(CIA_AT_SC) && is4) goto none;
1544 if (o == GOF(RESVN) && 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;
1548
1549 if (sz == 1) {
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;
1570 }
1571
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;
1605
1606 /* FP admin related */
1607 if (o == GOF(FPROUND) && is4) goto none;
1608 if (o == GOF(EMWARN) && is4) goto none;
1609
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;
1643
sewardjaae82082008-10-21 23:10:18 +00001644 /* Altivec admin related */
1645 if (o == GOF(VRSAVE) && is4) goto none;
1646
sewardj024598e2008-09-18 14:43:05 +00001647 VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz);
1648 tl_assert(0);
1649# undef GOF
1650
1651 /* -------------------- ppc64 -------------------- */
1652
1653# elif defined(VGA_ppc64)
1654
1655# define GOF(_fieldname) \
1656 (offsetof(VexGuestPPC64State,guest_##_fieldname))
1657
1658 Int o = offset;
1659 Int sz = szB;
1660 Bool is4 = sz == 4;
1661 Bool is8 = sz == 8;
1662
1663 tl_assert(sz > 0);
1664 tl_assert(host_is_big_endian());
1665
1666 /* Set default state to "does not intersect any int register". */
1667 VG_(memset)( iii, 0, sizeof(*iii) );
1668
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;
1702
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(CIA_AT_SC) && is8) goto none;
1708 if (o == GOF(RESVN) && is8) goto none;
1709 if (o == GOF(TISTART) && is8) goto none;
1710 if (o == GOF(TILEN) && is8) goto none;
1711 if (o == GOF(REDIR_SP) && is8) goto none;
1712
1713 if (sz == 1) {
1714 if (o == GOF(XER_SO)) goto none;
1715 if (o == GOF(XER_OV)) goto none;
1716 if (o == GOF(XER_CA)) goto none;
1717 if (o == GOF(XER_BC)) goto none;
1718 if (o == GOF(CR0_321)) goto none;
1719 if (o == GOF(CR0_0)) goto none;
1720 if (o == GOF(CR1_321)) goto none;
1721 if (o == GOF(CR1_0)) goto none;
1722 if (o == GOF(CR2_321)) goto none;
1723 if (o == GOF(CR2_0)) goto none;
1724 if (o == GOF(CR3_321)) goto none;
1725 if (o == GOF(CR3_0)) goto none;
1726 if (o == GOF(CR4_321)) goto none;
1727 if (o == GOF(CR4_0)) goto none;
1728 if (o == GOF(CR5_321)) goto none;
1729 if (o == GOF(CR5_0)) goto none;
1730 if (o == GOF(CR6_321)) goto none;
1731 if (o == GOF(CR6_0)) goto none;
1732 if (o == GOF(CR7_321)) goto none;
1733 if (o == GOF(CR7_0)) goto none;
1734 }
1735
1736 /* Exact accesses to FP registers */
1737 if (o == GOF(FPR0) && is8) goto none;
1738 if (o == GOF(FPR1) && is8) goto none;
1739 if (o == GOF(FPR2) && is8) goto none;
1740 if (o == GOF(FPR3) && is8) goto none;
1741 if (o == GOF(FPR4) && is8) goto none;
1742 if (o == GOF(FPR5) && is8) goto none;
1743 if (o == GOF(FPR6) && is8) goto none;
1744 if (o == GOF(FPR7) && is8) goto none;
1745 if (o == GOF(FPR8) && is8) goto none;
1746 if (o == GOF(FPR9) && is8) goto none;
1747 if (o == GOF(FPR10) && is8) goto none;
1748 if (o == GOF(FPR11) && is8) goto none;
1749 if (o == GOF(FPR12) && is8) goto none;
1750 if (o == GOF(FPR13) && is8) goto none;
1751 if (o == GOF(FPR14) && is8) goto none;
1752 if (o == GOF(FPR15) && is8) goto none;
1753 if (o == GOF(FPR16) && is8) goto none;
1754 if (o == GOF(FPR17) && is8) goto none;
1755 if (o == GOF(FPR18) && is8) goto none;
1756 if (o == GOF(FPR19) && is8) goto none;
1757 if (o == GOF(FPR20) && is8) goto none;
1758 if (o == GOF(FPR21) && is8) goto none;
1759 if (o == GOF(FPR22) && is8) goto none;
1760 if (o == GOF(FPR23) && is8) goto none;
1761 if (o == GOF(FPR24) && is8) goto none;
1762 if (o == GOF(FPR25) && is8) goto none;
1763 if (o == GOF(FPR26) && is8) goto none;
1764 if (o == GOF(FPR27) && is8) goto none;
1765 if (o == GOF(FPR28) && is8) goto none;
1766 if (o == GOF(FPR29) && is8) goto none;
1767 if (o == GOF(FPR30) && is8) goto none;
1768 if (o == GOF(FPR31) && is8) goto none;
1769
1770 /* FP admin related */
1771 if (o == GOF(FPROUND) && is4) goto none;
1772 if (o == GOF(EMWARN) && is4) goto none;
1773
1774 /* Altivec registers */
1775 if (o == GOF(VR0) && sz == 16) goto none;
1776 if (o == GOF(VR1) && sz == 16) goto none;
1777 if (o == GOF(VR2) && sz == 16) goto none;
1778 if (o == GOF(VR3) && sz == 16) goto none;
1779 if (o == GOF(VR4) && sz == 16) goto none;
1780 if (o == GOF(VR5) && sz == 16) goto none;
1781 if (o == GOF(VR6) && sz == 16) goto none;
1782 if (o == GOF(VR7) && sz == 16) goto none;
1783 if (o == GOF(VR8) && sz == 16) goto none;
1784 if (o == GOF(VR9) && sz == 16) goto none;
1785 if (o == GOF(VR10) && sz == 16) goto none;
1786 if (o == GOF(VR11) && sz == 16) goto none;
1787 if (o == GOF(VR12) && sz == 16) goto none;
1788 if (o == GOF(VR13) && sz == 16) goto none;
1789 if (o == GOF(VR14) && sz == 16) goto none;
1790 if (o == GOF(VR15) && sz == 16) goto none;
1791 if (o == GOF(VR16) && sz == 16) goto none;
1792 if (o == GOF(VR17) && sz == 16) goto none;
1793 if (o == GOF(VR18) && sz == 16) goto none;
1794 if (o == GOF(VR19) && sz == 16) goto none;
1795 if (o == GOF(VR20) && sz == 16) goto none;
1796 if (o == GOF(VR21) && sz == 16) goto none;
1797 if (o == GOF(VR22) && sz == 16) goto none;
1798 if (o == GOF(VR23) && sz == 16) goto none;
1799 if (o == GOF(VR24) && sz == 16) goto none;
1800 if (o == GOF(VR25) && sz == 16) goto none;
1801 if (o == GOF(VR26) && sz == 16) goto none;
1802 if (o == GOF(VR27) && sz == 16) goto none;
1803 if (o == GOF(VR28) && sz == 16) goto none;
1804 if (o == GOF(VR29) && sz == 16) goto none;
1805 if (o == GOF(VR30) && sz == 16) goto none;
1806 if (o == GOF(VR31) && sz == 16) goto none;
1807
sewardjaae82082008-10-21 23:10:18 +00001808 /* Altivec admin related */
1809 if (o == GOF(VRSAVE) && is4) goto none;
1810
sewardj024598e2008-09-18 14:43:05 +00001811 VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz);
1812 tl_assert(0);
1813# undef GOF
1814
1815
1816# else
1817# error "FIXME: not implemented for this architecture"
1818# endif
1819
1820 exactly1:
1821 iii->n_offsets = -1;
1822 return;
1823 none:
1824 iii->n_offsets = 0;
1825 return;
1826 contains_o:
1827 tl_assert(o >= 0 && 0 == (o % sizeof(UWord)));
1828 iii->n_offsets = 1;
1829 iii->offsets[0] = o;
1830 return;
1831}
1832
1833
1834/* Does 'arr' describe an indexed guest state section containing host
1835 words, that we want to shadow? */
1836
1837static Bool is_integer_guest_reg_array ( IRRegArray* arr )
1838{
1839 /* --------------------- x86 --------------------- */
1840# if defined(VGA_x86)
1841 /* The x87 tag array. */
1842 if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0])
1843 && arr->elemTy == Ity_I8 && arr->nElems == 8)
1844 return False;
1845 /* The x87 register array. */
1846 if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0])
1847 && arr->elemTy == Ity_F64 && arr->nElems == 8)
1848 return False;
1849
1850 VG_(printf)("is_integer_guest_reg_array(x86): unhandled: ");
1851 ppIRRegArray(arr);
1852 VG_(printf)("\n");
1853 tl_assert(0);
1854
1855 /* -------------------- amd64 -------------------- */
1856# elif defined(VGA_amd64)
1857 /* The x87 tag array. */
1858 if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0])
1859 && arr->elemTy == Ity_I8 && arr->nElems == 8)
1860 return False;
1861 /* The x87 register array. */
1862 if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0])
1863 && arr->elemTy == Ity_F64 && arr->nElems == 8)
1864 return False;
1865
1866 VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: ");
1867 ppIRRegArray(arr);
1868 VG_(printf)("\n");
1869 tl_assert(0);
1870
1871 /* -------------------- ppc32 -------------------- */
1872# elif defined(VGA_ppc32)
1873 /* The redir stack. */
1874 if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0])
1875 && arr->elemTy == Ity_I32
1876 && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE)
1877 return True;
1878
1879 VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: ");
1880 ppIRRegArray(arr);
1881 VG_(printf)("\n");
1882 tl_assert(0);
1883
1884 /* -------------------- ppc64 -------------------- */
1885# elif defined(VGA_ppc64)
1886 /* The redir stack. */
1887 if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0])
1888 && arr->elemTy == Ity_I64
1889 && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE)
1890 return True;
1891
1892 VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: ");
1893 ppIRRegArray(arr);
1894 VG_(printf)("\n");
1895 tl_assert(0);
1896
1897# else
1898# error "FIXME: not implemented for this architecture"
1899# endif
1900}
1901
1902
1903// END move this uglyness to pc_machine.c
1904
1905/* returns True iff given slice exactly matches an int reg. Merely
1906 a convenience wrapper around get_IntRegInfo. */
1907static Bool is_integer_guest_reg ( Int offset, Int szB )
1908{
1909 IntRegInfo iii;
1910 get_IntRegInfo( &iii, offset, szB );
1911 tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
1912 return iii.n_offsets == -1;
1913}
1914
1915/* these assume guest and host have the same endianness and
1916 word size (probably). */
1917static UWord get_guest_intreg ( ThreadId tid, Int shadowNo,
njnc4431bf2009-01-15 21:29:24 +00001918 PtrdiffT offset, SizeT size )
sewardj024598e2008-09-18 14:43:05 +00001919{
1920 UChar tmp[ 2 + sizeof(UWord) ];
1921 tl_assert(size == sizeof(UWord));
1922 tl_assert(0 == (offset % sizeof(UWord)));
1923 VG_(memset)(tmp, 0, sizeof(tmp));
1924 tmp[0] = 0x31;
1925 tmp[ sizeof(tmp)-1 ] = 0x27;
1926 VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size);
1927 tl_assert(tmp[0] == 0x31);
1928 tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27);
1929 return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */
1930}
1931static void put_guest_intreg ( ThreadId tid, Int shadowNo,
njnc4431bf2009-01-15 21:29:24 +00001932 PtrdiffT offset, SizeT size, UWord w )
sewardj024598e2008-09-18 14:43:05 +00001933{
1934 tl_assert(size == sizeof(UWord));
1935 tl_assert(0 == (offset % sizeof(UWord)));
1936 VG_(set_shadow_regs_area)(tid, shadowNo, offset, size,
1937 (const UChar*)&w);
1938}
1939
1940/* Initialise the integer shadow registers to UNKNOWN. This is a bit
1941 of a nasty kludge, but it does mean we don't need to know which
1942 registers we really need to initialise -- simply assume that all
1943 integer registers will be naturally aligned w.r.t. the start of the
1944 guest state, and fill in all possible entries. */
1945static void init_shadow_registers ( ThreadId tid )
1946{
1947 Int i, wordSzB = sizeof(UWord);
1948 for (i = 0; i < MC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) {
1949 put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN );
1950 }
1951}
1952
njnc4431bf2009-01-15 21:29:24 +00001953static void post_reg_write_nonptr ( ThreadId tid, PtrdiffT offset, SizeT size )
sewardj024598e2008-09-18 14:43:05 +00001954{
1955 // syscall_return: Default is non-pointer. If it really is a pointer
1956 // (eg. for mmap()), SK_(post_syscall) sets it again afterwards.
1957 //
1958 // clientreq_return: All the global client requests return non-pointers
1959 // (except possibly CLIENT_CALL[0123], but they're handled by
1960 // post_reg_write_clientcall, not here).
1961 //
1962 if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1963 put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR );
1964 } else {
1965 tl_assert(0);
1966 }
1967 // VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR );
1968}
1969
1970static void post_reg_write_nonptr_or_unknown ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00001971 PtrdiffT offset, SizeT size )
sewardj024598e2008-09-18 14:43:05 +00001972{
1973 // deliver_signal: called from two places; one sets the reg to zero, the
1974 // other sets the stack pointer.
1975 //
1976 if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1977 put_guest_intreg(
1978 tid, 1/*shadowno*/, offset, size,
1979 (UWord)nonptr_or_unknown(
1980 get_guest_intreg( tid, 0/*shadowno*/,
1981 offset, size )));
1982 } else {
1983 tl_assert(0);
1984 }
1985}
1986
1987void h_post_reg_write_demux ( CorePart part, ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00001988 PtrdiffT guest_state_offset, SizeT size)
sewardj024598e2008-09-18 14:43:05 +00001989{
1990 if (0)
1991 VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
1992 (Int)tid, (Int)part,
1993 guest_state_offset, size);
1994 switch (part) {
1995 case Vg_CoreStartup:
1996 /* This is a bit of a kludge since for any Vg_CoreStartup
1997 event we overwrite the entire shadow register set. But
1998 that's ok - we're only called once with
1999 part==Vg_CoreStartup event, and in that case the supplied
2000 offset & size cover the entire guest state anyway. */
2001 init_shadow_registers(tid);
2002 break;
2003 case Vg_CoreSysCall:
2004 if (0) VG_(printf)("ZZZZZZZ p_r_w -> NONPTR\n");
2005 post_reg_write_nonptr( tid, guest_state_offset, size );
2006 break;
2007 case Vg_CoreClientReq:
2008 post_reg_write_nonptr( tid, guest_state_offset, size );
2009 break;
2010 case Vg_CoreSignal:
2011 post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size );
2012 break;
2013 default:
2014 tl_assert(0);
2015 }
2016}
2017
njnc4431bf2009-01-15 21:29:24 +00002018void h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
sewardj024598e2008-09-18 14:43:05 +00002019 SizeT size, Addr f )
2020{
2021 UWord p;
2022
2023 // Having to do this is a bit nasty...
2024 if (f == (Addr)h_replace_malloc
2025 || f == (Addr)h_replace___builtin_new
2026 || f == (Addr)h_replace___builtin_vec_new
2027 || f == (Addr)h_replace_calloc
2028 || f == (Addr)h_replace_memalign
2029 || f == (Addr)h_replace_realloc)
2030 {
2031 // We remembered the last added segment; make sure it's the right one.
2032 /* What's going on: at this point, the scheduler has just called
2033 'f' -- one of our malloc replacement functions -- and it has
2034 returned. The return value has been written to the guest
2035 state of thread 'tid', offset 'guest_state_offset' length
2036 'size'. We need to look at that return value and set the
2037 shadow return value accordingly. The shadow return value
2038 required is handed to us "under the counter" through the
2039 global variable 'last_seg_added'. This is all very ugly, not
2040 to mention, non-thread-safe should V ever become
2041 multithreaded. */
2042 /* assert the place where the return value is is a legit int reg */
2043 tl_assert(is_integer_guest_reg(guest_state_offset, size));
2044 /* Now we need to look at the returned value, to see whether the
2045 malloc succeeded or not. */
2046 p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size);
2047 if ((UWord)NULL == p) {
2048 // if alloc failed, eg. realloc on bogus pointer
2049 put_guest_intreg(tid, 1/*first-shadow*/,
2050 guest_state_offset, size, (UWord)NONPTR );
2051 } else {
2052 // alloc didn't fail. Check we have the correct segment.
2053 tl_assert(p == last_seg_added->addr);
2054 put_guest_intreg(tid, 1/*first-shadow*/,
2055 guest_state_offset, size, (UWord)last_seg_added );
2056 }
2057 }
2058 else if (f == (Addr)h_replace_free
2059 || f == (Addr)h_replace___builtin_delete
2060 || f == (Addr)h_replace___builtin_vec_delete
2061 // || f == (Addr)VG_(cli_block_size)
2062 || f == (Addr)VG_(message))
2063 {
2064 // Probably best to set the (non-existent!) return value to
2065 // non-pointer.
2066 tl_assert(is_integer_guest_reg(guest_state_offset, size));
2067 put_guest_intreg(tid, 1/*first-shadow*/,
2068 guest_state_offset, size, (UWord)NONPTR );
2069 }
2070 else {
2071 // Anything else, probably best to set return value to non-pointer.
2072 //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN);
2073 Char fbuf[100];
2074 VG_(printf)("f = %#lx\n", f);
2075 VG_(get_fnname)(f, fbuf, 100);
2076 VG_(printf)("name = %s\n", fbuf);
2077 VG_(tool_panic)("argh: clientcall");
2078 }
2079}
2080
2081
2082//zz /*--------------------------------------------------------------------*/
2083//zz /*--- Sanity checking ---*/
2084//zz /*--------------------------------------------------------------------*/
2085//zz
2086//zz /* Check that nobody has spuriously claimed that the first or last 16
2087//zz pages (64 KB) of address space have become accessible. Failure of
2088//zz the following do not per se indicate an internal consistency
2089//zz problem, but they are so likely to that we really want to know
2090//zz about it if so. */
2091//zz Bool pc_replace_cheap_sanity_check) ( void )
2092//zz {
2093//zz if (IS_DISTINGUISHED_SM(primary_map[0])
2094//zz /* kludge: kernel drops a page up at top of address range for
2095//zz magic "optimized syscalls", so we can no longer check the
2096//zz highest page */
2097//zz /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
2098//zz )
2099//zz return True;
2100//zz else
2101//zz return False;
2102//zz }
2103//zz
2104//zz Bool SK_(expensive_sanity_check) ( void )
2105//zz {
2106//zz Int i;
2107//zz
2108//zz /* Make sure nobody changed the distinguished secondary. */
2109//zz for (i = 0; i < SEC_MAP_WORDS; i++)
2110//zz if (distinguished_secondary_map.vseg[i] != UNKNOWN)
2111//zz return False;
2112//zz
2113//zz return True;
2114//zz }
2115
2116
2117/*--------------------------------------------------------------------*/
2118/*--- System calls ---*/
2119/*--------------------------------------------------------------------*/
2120
2121void h_pre_syscall ( ThreadId tid, UInt sysno )
2122{
2123 /* we don't do anything at the pre-syscall point */
2124}
2125
2126/* The post-syscall table is a table of pairs (number, flag).
2127
2128 'flag' is only ever zero or one. If it is zero, it indicates that
2129 default handling for that syscall is required -- namely that the
2130 syscall is deemed to return NONPTR. This is the case for the vast
2131 majority of syscalls. If it is one then some special
2132 syscall-specific handling is is required. No further details of it
2133 are stored in the table.
2134
2135 On Linux, 'number' is a __NR_xxx constant.
2136
2137 On AIX5, 'number' is an Int*, which points to the Int variable
2138 holding the currently assigned number for this syscall.
2139
2140 When querying the table, we compare the supplied syscall number
2141 with the 'number' field (directly on Linux, after dereferencing on
2142 AIX5), to find the relevant entry. This requires a linear search
2143 of the table. To stop the costs getting too high, the table is
2144 incrementally rearranged after each search, to move commonly
2145 requested items a bit closer to the front.
2146
2147 The table is built once, the first time it is used. After that we
2148 merely query it (and reorder the entries as a result). */
2149
2150static XArray* /* of UWordPair */ post_syscall_table = NULL;
2151
2152static void setup_post_syscall_table ( void )
2153{
2154 tl_assert(!post_syscall_table);
2155 post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1",
2156 VG_(free), sizeof(UWordPair) );
2157 tl_assert(post_syscall_table);
2158
2159 /* --------------- LINUX --------------- */
2160
2161# if defined(VGO_linux)
2162
2163# define ADD(_flag, _syscallname) \
2164 do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2165 VG_(addToXA)( post_syscall_table, &p ); \
2166 } while (0)
2167
2168 /* These ones definitely don't return pointers. They're not
2169 particularly grammatical, either. */
2170
2171# if defined(__NR__llseek)
2172 ADD(0, __NR__llseek);
2173# endif
2174 ADD(0, __NR__sysctl);
2175# if defined(__NR__newselect)
2176 ADD(0, __NR__newselect);
2177# endif
2178# if defined(__NR_accept)
2179 ADD(0, __NR_accept);
2180# endif
2181 ADD(0, __NR_access);
tom332ffec2009-01-05 12:16:21 +00002182 ADD(0, __NR_alarm);
sewardj024598e2008-09-18 14:43:05 +00002183# if defined(__NR_bind)
2184 ADD(0, __NR_bind);
2185# endif
2186# if defined(__NR_chdir)
2187 ADD(0, __NR_chdir);
2188# endif
2189 ADD(0, __NR_chmod);
2190 ADD(0, __NR_chown);
sewardj41d5dea2009-01-24 10:52:32 +00002191# if defined(__NR_chown32)
2192 ADD(0, __NR_chown32);
2193# endif
sewardj024598e2008-09-18 14:43:05 +00002194 ADD(0, __NR_clock_getres);
2195 ADD(0, __NR_clock_gettime);
2196 ADD(0, __NR_clone);
2197 ADD(0, __NR_close);
2198# if defined(__NR_connect)
2199 ADD(0, __NR_connect);
2200# endif
tom332ffec2009-01-05 12:16:21 +00002201 ADD(0, __NR_creat);
sewardj024598e2008-09-18 14:43:05 +00002202 ADD(0, __NR_dup);
2203 ADD(0, __NR_dup2);
2204 ADD(0, __NR_execve); /* presumably we see this because the call failed? */
2205 ADD(0, __NR_exit); /* hmm, why are we still alive? */
2206 ADD(0, __NR_exit_group);
2207 ADD(0, __NR_fadvise64);
2208 ADD(0, __NR_fchmod);
2209 ADD(0, __NR_fchown);
2210# if defined(__NR_fchown32)
2211 ADD(0, __NR_fchown32);
2212# endif
2213 ADD(0, __NR_fcntl);
2214# if defined(__NR_fcntl64)
2215 ADD(0, __NR_fcntl64);
2216# endif
2217 ADD(0, __NR_fdatasync);
sewardj33c57f22009-01-26 00:09:08 +00002218 ADD(0, __NR_flock);
sewardj024598e2008-09-18 14:43:05 +00002219 ADD(0, __NR_fstat);
2220# if defined(__NR_fstat64)
2221 ADD(0, __NR_fstat64);
2222# endif
2223 ADD(0, __NR_fstatfs);
2224 ADD(0, __NR_fsync);
2225 ADD(0, __NR_ftruncate);
2226# if defined(__NR_ftruncate64)
2227 ADD(0, __NR_ftruncate64);
2228# endif
2229 ADD(0, __NR_futex);
2230 ADD(0, __NR_getcwd);
2231 ADD(0, __NR_getdents); // something to do with teeth
2232 ADD(0, __NR_getdents64);
2233 ADD(0, __NR_getegid);
2234# if defined(__NR_getegid32)
2235 ADD(0, __NR_getegid32);
2236# endif
2237 ADD(0, __NR_geteuid);
2238# if defined(__NR_geteuid32)
2239 ADD(0, __NR_geteuid32);
2240# endif
2241 ADD(0, __NR_getgid);
2242# if defined(__NR_getgid32)
2243 ADD(0, __NR_getgid32);
2244# endif
2245 ADD(0, __NR_getitimer);
2246# if defined(__NR_getpeername)
2247 ADD(0, __NR_getpeername);
2248# endif
2249 ADD(0, __NR_getpid);
sewardj7d769112008-10-30 01:44:03 +00002250 ADD(0, __NR_getpgrp);
sewardj024598e2008-09-18 14:43:05 +00002251 ADD(0, __NR_getppid);
2252 ADD(0, __NR_getresgid);
2253 ADD(0, __NR_getresuid);
2254 ADD(0, __NR_getrlimit);
tom332ffec2009-01-05 12:16:21 +00002255 ADD(0, __NR_getrusage);
sewardj024598e2008-09-18 14:43:05 +00002256# if defined(__NR_getsockname)
2257 ADD(0, __NR_getsockname);
2258# endif
2259# if defined(__NR_getsockopt)
2260 ADD(0, __NR_getsockopt);
2261# endif
sewardj41d5dea2009-01-24 10:52:32 +00002262 ADD(0, __NR_gettid);
sewardj024598e2008-09-18 14:43:05 +00002263 ADD(0, __NR_gettimeofday);
2264 ADD(0, __NR_getuid);
2265# if defined(__NR_getuid32)
2266 ADD(0, __NR_getuid32);
2267# endif
2268 ADD(0, __NR_getxattr);
sewardj738db7b2008-10-20 10:30:08 +00002269 ADD(0, __NR_inotify_add_watch);
sewardj024598e2008-09-18 14:43:05 +00002270 ADD(0, __NR_inotify_init);
sewardj738db7b2008-10-20 10:30:08 +00002271 ADD(0, __NR_inotify_rm_watch);
sewardj024598e2008-09-18 14:43:05 +00002272 ADD(0, __NR_ioctl); // ioctl -- assuming no pointers returned
sewardj33c57f22009-01-26 00:09:08 +00002273 ADD(0, __NR_ioprio_get);
sewardj024598e2008-09-18 14:43:05 +00002274 ADD(0, __NR_kill);
2275 ADD(0, __NR_link);
2276# if defined(__NR_listen)
2277 ADD(0, __NR_listen);
2278# endif
2279 ADD(0, __NR_lseek);
2280 ADD(0, __NR_lstat);
2281# if defined(__NR_lstat64)
2282 ADD(0, __NR_lstat64);
2283# endif
2284 ADD(0, __NR_madvise);
2285 ADD(0, __NR_mkdir);
sewardj33c57f22009-01-26 00:09:08 +00002286 ADD(0, __NR_mlock);
sewardj024598e2008-09-18 14:43:05 +00002287 ADD(0, __NR_mprotect);
2288 ADD(0, __NR_munmap); // die_mem_munmap already called, segment remove);
sewardj738db7b2008-10-20 10:30:08 +00002289 ADD(0, __NR_nanosleep);
sewardj024598e2008-09-18 14:43:05 +00002290 ADD(0, __NR_open);
2291 ADD(0, __NR_pipe);
2292 ADD(0, __NR_poll);
2293 ADD(0, __NR_pread64);
2294 ADD(0, __NR_pwrite64);
2295 ADD(0, __NR_read);
2296 ADD(0, __NR_readlink);
2297 ADD(0, __NR_readv);
2298# if defined(__NR_recvfrom)
2299 ADD(0, __NR_recvfrom);
2300# endif
2301# if defined(__NR_recvmsg)
2302 ADD(0, __NR_recvmsg);
2303# endif
2304 ADD(0, __NR_rename);
2305 ADD(0, __NR_rmdir);
2306 ADD(0, __NR_rt_sigaction);
2307 ADD(0, __NR_rt_sigprocmask);
2308 ADD(0, __NR_rt_sigreturn); /* not sure if we should see this or not */
2309 ADD(0, __NR_sched_get_priority_max);
2310 ADD(0, __NR_sched_get_priority_min);
sewardj738db7b2008-10-20 10:30:08 +00002311 ADD(0, __NR_sched_getaffinity);
sewardj024598e2008-09-18 14:43:05 +00002312 ADD(0, __NR_sched_getparam);
2313 ADD(0, __NR_sched_getscheduler);
sewardj41d5dea2009-01-24 10:52:32 +00002314 ADD(0, __NR_sched_setaffinity);
sewardj024598e2008-09-18 14:43:05 +00002315 ADD(0, __NR_sched_setscheduler);
2316 ADD(0, __NR_sched_yield);
2317 ADD(0, __NR_select);
sewardj33c57f22009-01-26 00:09:08 +00002318# if defined(__NR_semctl)
2319 ADD(0, __NR_semctl);
2320# endif
2321# if defined(__NR_semget)
2322 ADD(0, __NR_semget);
2323# endif
2324# if defined(__NR_semop)
2325 ADD(0, __NR_semop);
2326# endif
sewardj024598e2008-09-18 14:43:05 +00002327# if defined(__NR_sendto)
2328 ADD(0, __NR_sendto);
2329# endif
tom332ffec2009-01-05 12:16:21 +00002330# if defined(__NR_sendmsg)
2331 ADD(0, __NR_sendmsg);
2332# endif
sewardj024598e2008-09-18 14:43:05 +00002333 ADD(0, __NR_set_robust_list);
2334# if defined(__NR_set_thread_area)
2335 ADD(0, __NR_set_thread_area);
2336# endif
2337 ADD(0, __NR_set_tid_address);
2338 ADD(0, __NR_setitimer);
sewardj7d769112008-10-30 01:44:03 +00002339 ADD(0, __NR_setpgid);
sewardj024598e2008-09-18 14:43:05 +00002340 ADD(0, __NR_setrlimit);
2341 ADD(0, __NR_setsid);
2342# if defined(__NR_setsockopt)
2343 ADD(0, __NR_setsockopt);
2344# endif
2345# if defined(__NR_shmctl)
2346 ADD(0, __NR_shmctl);
2347 ADD(0, __NR_shmdt);
2348# endif
2349# if defined(__NR_shutdown)
2350 ADD(0, __NR_shutdown);
2351# endif
sewardj41d5dea2009-01-24 10:52:32 +00002352 ADD(0, __NR_sigaltstack);
sewardj024598e2008-09-18 14:43:05 +00002353# if defined(__NR_socket)
2354 ADD(0, __NR_socket);
2355# endif
2356# if defined(__NR_socketcall)
2357 ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */
2358# endif
sewardj23e8a292009-01-07 09:35:10 +00002359# if defined(__NR_socketpair)
2360 ADD(0, __NR_socketpair);
2361# endif
sewardj024598e2008-09-18 14:43:05 +00002362# if defined(__NR_statfs64)
2363 ADD(0, __NR_statfs64);
2364# endif
2365# if defined(__NR_sigreturn)
2366 ADD(0, __NR_sigreturn); /* not sure if we should see this or not */
2367# endif
2368# if defined(__NR_stat64)
2369 ADD(0, __NR_stat64);
2370# endif
2371 ADD(0, __NR_stat);
2372 ADD(0, __NR_statfs);
2373 ADD(0, __NR_symlink);
2374 ADD(0, __NR_sysinfo);
2375 ADD(0, __NR_tgkill);
2376 ADD(0, __NR_time);
2377 ADD(0, __NR_times);
2378 ADD(0, __NR_truncate);
2379# if defined(__NR_truncate64)
2380 ADD(0, __NR_truncate64);
2381# endif
2382# if defined(__NR_ugetrlimit)
2383 ADD(0, __NR_ugetrlimit);
2384# endif
2385 ADD(0, __NR_umask);
2386 ADD(0, __NR_uname);
2387 ADD(0, __NR_unlink);
2388 ADD(0, __NR_utime);
2389# if defined(__NR_waitpid)
2390 ADD(0, __NR_waitpid);
2391# endif
2392 ADD(0, __NR_wait4);
2393 ADD(0, __NR_write);
2394 ADD(0, __NR_writev);
2395
2396 /* Whereas the following need special treatment */
2397# if defined(__NR_arch_prctl)
2398 ADD(1, __NR_arch_prctl);
2399# endif
2400 ADD(1, __NR_brk);
2401 ADD(1, __NR_mmap);
2402# if defined(__NR_mmap2)
2403 ADD(1, __NR_mmap2);
2404# endif
2405# if defined(__NR_shmat)
2406 ADD(1, __NR_shmat);
2407# endif
2408# if defined(__NR_shmget)
2409 ADD(1, __NR_shmget);
2410# endif
2411
2412 /* --------------- AIX5 --------------- */
2413
2414# elif defined(VGO_aix5)
2415
2416# define ADD(_flag, _syscallname) \
2417 do { \
2418 UWordPair p; \
2419 if ((_syscallname) != __NR_AIX5_UNKNOWN) { \
2420 p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \
2421 VG_(addToXA)( post_syscall_table, &p ); \
2422 } \
2423 } while (0)
2424
2425 /* Just a minimal set of handlers, enough to make
2426 a 32- and 64-bit hello-world program run. */
2427 ADD(1, __NR_AIX5___loadx); /* not sure what to do here */
2428 ADD(0, __NR_AIX5__exit);
2429 ADD(0, __NR_AIX5_access);
2430 ADD(0, __NR_AIX5_getgidx);
2431 ADD(0, __NR_AIX5_getuidx);
2432 ADD(0, __NR_AIX5_kfcntl);
2433 ADD(0, __NR_AIX5_kioctl);
2434 ADD(1, __NR_AIX5_kload); /* not sure what to do here */
2435 ADD(0, __NR_AIX5_kwrite);
2436
2437# else
2438# error "Unsupported OS"
2439# endif
2440
2441# undef ADD
2442}
2443
2444
2445void h_post_syscall ( ThreadId tid, UInt sysno, SysRes res )
2446{
2447 Word i, n;
2448 UWordPair* pair;
2449
2450 if (!post_syscall_table)
2451 setup_post_syscall_table();
2452
2453 /* search for 'sysno' in the post_syscall_table */
2454 n = VG_(sizeXA)( post_syscall_table );
2455 for (i = 0; i < n; i++) {
2456 pair = VG_(indexXA)( post_syscall_table, i );
2457# if defined(VGO_linux)
2458 if (pair->uw1 == (UWord)sysno)
2459 break;
2460# elif defined(VGO_aix5)
2461 if (*(Int*)(pair->uw1) == (Int)sysno)
2462 break;
2463# else
2464# error "Unsupported OS"
2465# endif
2466 }
2467
2468 tl_assert(i >= 0 && i <= n);
2469
2470 if (i == n) {
2471 VG_(printf)("sysno == %u\n", sysno);
2472# if defined(VGO_aix5)
2473 VG_(printf)("syscallnm == %s\n",
2474 VG_(aix5_sysno_to_sysname)(sysno));
2475# endif
2476 VG_(tool_panic)("unhandled syscall");
2477 }
2478
2479 /* So we found the relevant entry. Move it one step
2480 forward so as to speed future accesses to it. */
2481 if (i > 0) {
2482 UWordPair tmp, *p, *q;
2483 p = VG_(indexXA)( post_syscall_table, i-1 );
2484 q = VG_(indexXA)( post_syscall_table, i-0 );
2485 tmp = *p;
2486 *p = *q;
2487 *q = tmp;
2488 i--;
2489 }
2490
2491 /* Deal with the common case */
2492 pair = VG_(indexXA)( post_syscall_table, i );
2493 if (pair->uw2 == 0) {
2494 /* the common case */
2495 VG_(set_syscall_return_shadows)(
2496 tid, /* retval */ (UWord)NONPTR, 0,
2497 /* error */ (UWord)NONPTR, 0
2498 );
2499 return;
2500 }
2501
2502 /* Special handling for all remaining cases */
2503 tl_assert(pair->uw2 == 1);
2504
2505# if defined(__NR_arch_prctl)
2506 if (sysno == __NR_arch_prctl) {
2507 /* This is nasty. On amd64-linux, arch_prctl may write a
2508 value to guest_FS_ZERO, and we need to shadow that value.
2509 Hence apply nonptr_or_unknown to it here, after the
2510 syscall completes. */
2511 post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO,
2512 PC_SZB_FS_ZERO );
2513 VG_(set_syscall_return_shadows)(
2514 tid, /* retval */ (UWord)NONPTR, 0,
2515 /* error */ (UWord)NONPTR, 0
2516 );
2517 return;
2518 }
2519# endif
2520
2521# if defined(__NR_brk)
2522 // With brk(), result (of kernel syscall, not glibc wrapper) is a heap
2523 // pointer. Make the shadow UNKNOWN.
2524 if (sysno == __NR_brk) {
2525 VG_(set_syscall_return_shadows)(
2526 tid, /* retval */ (UWord)UNKNOWN, 0,
2527 /* error */ (UWord)NONPTR, 0
2528 );
2529 return;
2530 }
2531# endif
2532
2533 // With mmap, new_mem_mmap() has already been called and added the
2534 // segment (we did it there because we had the result address and size
2535 // handy). So just set the return value shadow.
2536 if (sysno == __NR_mmap
2537# if defined(__NR_mmap2)
2538 || sysno == __NR_mmap2
2539# endif
2540# if defined(__NR_AIX5___loadx)
2541 || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN)
2542# endif
2543# if defined(__NR_AIX5_kload)
2544 || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN)
2545# endif
2546 ) {
2547 if (res.isError) {
2548 // mmap() had an error, return value is a small negative integer
2549 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2550 /*err*/ (UWord)NONPTR, 0 );
2551 if (0) VG_(printf)("ZZZZZZZ mmap res -> NONPTR\n");
2552 } else {
2553 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2554 /*err*/ (UWord)NONPTR, 0 );
2555 if (0) VG_(printf)("ZZZZZZZ mmap res -> UNKNOWN\n");
2556 }
2557 return;
2558 }
2559
2560 // shmat uses the same scheme. We will just have had a
2561 // notification via new_mem_mmap. Just set the return value shadow.
2562# if defined(__NR_shmat)
2563 if (sysno == __NR_shmat) {
2564 if (res.isError) {
2565 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2566 /*err*/ (UWord)NONPTR, 0 );
2567 if (0) VG_(printf)("ZZZZZZZ shmat res -> NONPTR\n");
2568 } else {
2569 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2570 /*err*/ (UWord)NONPTR, 0 );
2571 if (0) VG_(printf)("ZZZZZZZ shmat res -> UNKNOWN\n");
2572 }
2573 return;
2574 }
2575# endif
2576
2577# if defined(__NR_shmget)
2578 if (sysno == __NR_shmget) {
2579 // FIXME: is this correct?
2580 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2581 /*err*/ (UWord)NONPTR, 0 );
2582 return;
2583 }
2584# endif
2585
2586 /* If we get here, it implies the corresponding entry in
2587 post_syscall_table has .w2 == 1, which in turn implies there
2588 should be special-case code for it above. */
2589 tl_assert(0);
2590}
2591
2592
2593/*--------------------------------------------------------------------*/
2594/*--- Functions called from generated code ---*/
2595/*--------------------------------------------------------------------*/
2596
2597#if SC_SEGS
2598static void checkSeg ( Seg vseg ) {
2599 tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM
2600 || Seg__plausible(vseg) );
2601}
2602#endif
2603
2604// XXX: could be more sophisticated -- actually track the lowest/highest
2605// valid address used by the program, and then return False for anything
2606// below that (using a suitable safety margin). Also, nothing above
2607// 0xc0000000 is valid [unless you've changed that in your kernel]
2608static inline Bool looks_like_a_pointer(Addr a)
2609{
2610# if defined(VGA_x86) || defined(VGA_ppc32)
2611 tl_assert(sizeof(UWord) == 4);
2612 return (a > 0x01000000UL && a < 0xFF000000UL);
2613# elif defined(VGA_amd64) || defined(VGA_ppc64)
2614 tl_assert(sizeof(UWord) == 8);
2615 return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL);
2616# else
2617# error "Unsupported architecture"
2618# endif
2619}
2620
2621static inline VG_REGPARM(1)
2622Seg* nonptr_or_unknown(UWord x)
2623{
2624 Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR;
2625 if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n",
2626 res==UNKNOWN ? "UUU" : "nnn", x);
2627 return res;
2628}
2629
2630//zz static __attribute__((regparm(1)))
2631//zz void print_BB_entry(UInt bb)
2632//zz {
2633//zz VG_(printf)("%u =\n", bb);
2634//zz }
2635
sewardj59347ff2008-12-23 02:31:22 +00002636//static ULong stats__tot_mem_refs = 0;
2637//static ULong stats__refs_in_a_seg = 0;
2638//static ULong stats__refs_lost_seg = 0;
sewardj024598e2008-09-18 14:43:05 +00002639
2640typedef
2641 struct { ExeContext* ec; UWord count; }
2642 Lossage;
2643
2644static OSet* lossage = NULL;
2645
sewardj59347ff2008-12-23 02:31:22 +00002646//static void inc_lossage ( ExeContext* ec )
2647//{
2648// Lossage key, *res, *nyu;
2649// key.ec = ec;
2650// key.count = 0; /* frivolous */
2651// res = VG_(OSetGen_Lookup)(lossage, &key);
2652// if (res) {
2653// tl_assert(res->ec == ec);
2654// res->count++;
2655// } else {
2656// nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage));
2657// tl_assert(nyu);
2658// nyu->ec = ec;
2659// nyu->count = 1;
2660// VG_(OSetGen_Insert)( lossage, nyu );
2661// }
2662//}
sewardj024598e2008-09-18 14:43:05 +00002663
2664static void init_lossage ( void )
2665{
2666 lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec),
2667 /*fastCmp*/NULL,
2668 VG_(malloc), "pc.h_main.il.1",
2669 VG_(free) );
2670 tl_assert(lossage);
2671}
2672
sewardj59347ff2008-12-23 02:31:22 +00002673//static void show_lossage ( void )
2674//{
2675// Lossage* elem;
2676// VG_(OSetGen_ResetIter)( lossage );
2677// while ( (elem = VG_(OSetGen_Next)(lossage)) ) {
2678// if (elem->count < 10) continue;
2679// //Char buf[100];
2680// //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1);
2681// //buf[sizeof(buf)-1] = 0;
2682// //VG_(printf)(" %,8lu %s\n", elem->count, buf);
2683// VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count);
2684// VG_(pp_ExeContext)(elem->ec);
2685// }
2686//}
sewardj024598e2008-09-18 14:43:05 +00002687
2688// This function is called *a lot*; inlining it sped up Konqueror by 20%.
2689static inline
2690void check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg)
2691{
sewardj024598e2008-09-18 14:43:05 +00002692#if 0
sewardj4815eb52008-10-20 23:33:49 +00002693 tl_assert(0);
2694 if (h_clo_lossage_check) {
sewardj024598e2008-09-18 14:43:05 +00002695 Seg* seg;
2696 stats__tot_mem_refs++;
2697 if (ISList__findI0( seglist, (Addr)m, &seg )) {
2698 /* m falls inside 'seg' (that is, we are making a memory
2699 reference inside 'seg'). Now, really mptr_vseg should be
2700 a tracked segment of some description. Badness is when
2701 mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point,
2702 since that means we've lost the type of it somehow: it
2703 shoud say that m points into a real segment (preferable
2704 'seg'), but it doesn't. */
2705 if (Seg__status_is_SegHeap(seg)) {
2706 stats__refs_in_a_seg++;
2707 if (UNKNOWN == mptr_vseg
2708 || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
2709 ExeContext* ec;
2710 Char buf[100];
2711 static UWord xx = 0;
2712 stats__refs_lost_seg++;
2713 ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
2714 inc_lossage(ec);
2715 if (0) {
2716 VG_(message)(Vg_DebugMsg, "");
2717 VG_(message)(Vg_DebugMsg,
2718 "Lossage %s %#lx sz %lu inside block alloc'd",
2719 is_write ? "wr" : "rd", m, (UWord)sz);
2720 VG_(pp_ExeContext)(Seg__where(seg));
2721 }
2722 if (xx++ < 0) {
2723 Addr ip = VG_(get_IP)( VG_(get_running_tid)() );
2724 (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1);
2725 buf[sizeof(buf)-1] = 0;
2726 VG_(printf)("lossage at %p %s\n", ec, buf );
2727 }
2728 }
2729 }
2730 }
sewardj024598e2008-09-18 14:43:05 +00002731 } /* clo_lossage_check */
sewardj4815eb52008-10-20 23:33:49 +00002732#endif
sewardj024598e2008-09-18 14:43:05 +00002733
2734# if SC_SEGS
2735 checkSeg(mptr_vseg);
2736# endif
2737
2738 if (UNKNOWN == mptr_vseg) {
2739 // do nothing
2740
2741 } else if (BOTTOM == mptr_vseg) {
2742 // do nothing
2743
2744 } else if (NONPTR == mptr_vseg) {
2745 h_record_heap_error( m, sz, mptr_vseg, is_write );
2746
2747 } else {
2748 // check all segment ranges in the circle
2749 // if none match, warn about 1st seg
2750 // else, check matching one isn't freed
2751 Bool is_ok = False;
2752 Seg* curr = mptr_vseg;
2753 Addr mhi;
2754
2755 // Accesses partly outside range are an error, unless it's an aligned
2756 // word-sized read, and --partial-loads-ok=yes. This is to cope with
2757 // gcc's/glibc's habits of doing word-sized accesses that read past
2758 // the ends of arrays/strings.
2759 // JRS 2008-sept-11: couldn't this be moved off the critical path?
2760 if (!is_write && sz == sizeof(UWord)
2761 && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
2762 mhi = m;
2763 } else {
2764 mhi = m+sz-1;
2765 }
2766
2767 if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi);
2768 is_ok = curr->addr <= m && mhi < curr->addr + curr->szB;
2769
2770 // If it's an overrun/underrun of a freed block, don't give both
2771 // warnings, since the first one mentions that the block has been
2772 // freed.
2773 if ( ! is_ok || Seg__is_freed(curr) )
2774 h_record_heap_error( m, sz, mptr_vseg, is_write );
2775 }
2776}
2777
2778// ------------------ Load handlers ------------------ //
2779
2780/* On 32 bit targets, we will use:
2781 check_load1 check_load2 check_load4_P
2782 check_load4 (for 32-bit FP reads)
2783 check_load8 (for 64-bit FP reads)
2784 check_load16 (for xmm/altivec reads)
2785 On 64 bit targets, we will use:
2786 check_load1 check_load2 check_load4 check_load8_P
2787 check_load8 (for 64-bit FP reads)
2788 check_load16 (for xmm/altivec reads)
2789
2790 A "_P" handler reads a pointer from memory, and so returns a value
2791 to the generated code -- the pointer's shadow value. That implies
2792 that check_load4_P is only to be called on a 32 bit host and
2793 check_load8_P is only to be called on a 64 bit host. For all other
2794 cases no shadow value is returned; we merely check that the pointer
2795 (m) matches the block described by its shadow value (mptr_vseg).
2796*/
2797
2798// This handles 128 bit loads on both 32 bit and 64 bit targets.
2799static VG_REGPARM(2)
2800void check_load16(Addr m, Seg* mptr_vseg)
2801{
2802# if SC_SEGS
2803 checkSeg(mptr_vseg);
2804# endif
2805 check_load_or_store(/*is_write*/False, m, 16, mptr_vseg);
2806}
2807
2808// This handles 64 bit FP-or-otherwise-nonpointer loads on both
2809// 32 bit and 64 bit targets.
2810static VG_REGPARM(2)
2811void check_load8(Addr m, Seg* mptr_vseg)
2812{
2813# if SC_SEGS
2814 checkSeg(mptr_vseg);
2815# endif
2816 check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2817}
2818
2819// This handles 64 bit loads on 64 bit targets. It must
2820// not be called on 32 bit targets.
2821// return m.vseg
2822static VG_REGPARM(2)
2823Seg* check_load8_P(Addr m, Seg* mptr_vseg)
2824{
2825 Seg* vseg;
2826 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2827# if SC_SEGS
2828 checkSeg(mptr_vseg);
2829# endif
2830 check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2831 if (VG_IS_8_ALIGNED(m)) {
2832 vseg = get_mem_vseg(m);
2833 } else {
2834 vseg = nonptr_or_unknown( *(ULong*)m );
2835 }
2836 return vseg;
2837}
2838
2839// This handles 32 bit loads on 32 bit targets. It must
2840// not be called on 64 bit targets.
2841// return m.vseg
2842static VG_REGPARM(2)
2843Seg* check_load4_P(Addr m, Seg* mptr_vseg)
2844{
2845 Seg* vseg;
2846 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2847# if SC_SEGS
2848 checkSeg(mptr_vseg);
2849# endif
2850 check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2851 if (VG_IS_4_ALIGNED(m)) {
2852 vseg = get_mem_vseg(m);
2853 } else {
2854 vseg = nonptr_or_unknown( *(UInt*)m );
2855 }
2856 return vseg;
2857}
2858
2859// Used for both 32 bit and 64 bit targets.
2860static VG_REGPARM(2)
2861void check_load4(Addr m, Seg* mptr_vseg)
2862{
2863# if SC_SEGS
2864 checkSeg(mptr_vseg);
2865# endif
2866 check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2867}
2868
2869// Used for both 32 bit and 64 bit targets.
2870static VG_REGPARM(2)
2871void check_load2(Addr m, Seg* mptr_vseg)
2872{
2873# if SC_SEGS
2874 checkSeg(mptr_vseg);
2875# endif
2876 check_load_or_store(/*is_write*/False, m, 2, mptr_vseg);
2877}
2878
2879// Used for both 32 bit and 64 bit targets.
2880static VG_REGPARM(2)
2881void check_load1(Addr m, Seg* mptr_vseg)
2882{
2883# if SC_SEGS
2884 checkSeg(mptr_vseg);
2885# endif
2886 check_load_or_store(/*is_write*/False, m, 1, mptr_vseg);
2887}
2888
2889// ------------------ Store handlers ------------------ //
2890
2891/* On 32 bit targets, we will use:
2892 check_store1 check_store2 check_store4_P
2893 check_store4 (for 32-bit nonpointer stores)
2894 check_store8_ms4B_ls4B (for 64-bit stores)
2895 check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores)
2896
2897 On 64 bit targets, we will use:
2898 check_store1 check_store2 check_store4 check_store8_P
2899 check_store8_all8B (for 64-bit nonpointer stores)
2900 check_store16_ms8B_ls8B (for xmm/altivec stores)
2901
2902 A "_P" handler writes a pointer to memory, and so has an extra
2903 argument -- the pointer's shadow value. That implies that
2904 check_store4_P is only to be called on a 32 bit host and
2905 check_store8_P is only to be called on a 64 bit host. For all
2906 other cases, and for the misaligned _P cases, the strategy is to
2907 let the store go through, and then snoop around with
2908 nonptr_or_unknown to fix up the shadow values of any affected
2909 words. */
2910
2911/* Apply nonptr_or_unknown to all the words intersecting
2912 [a, a+len). */
2913static VG_REGPARM(2)
2914void nonptr_or_unknown_range ( Addr a, SizeT len )
2915{
2916 const SizeT wszB = sizeof(UWord);
2917 Addr wfirst = VG_ROUNDDN(a, wszB);
2918 Addr wlast = VG_ROUNDDN(a+len-1, wszB);
2919 Addr a2;
2920 tl_assert(wfirst <= wlast);
2921 for (a2 = wfirst ; a2 <= wlast; a2 += wszB) {
2922 set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 ));
2923 }
2924}
2925
2926// This handles 128 bit stores on 64 bit targets. The
2927// store data is passed in 2 pieces, the most significant
2928// bits first.
2929static VG_REGPARM(3)
2930void check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg,
2931 UWord ms8B, UWord ls8B)
2932{
2933 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2934# if SC_SEGS
2935 checkSeg(mptr_vseg);
2936# endif
2937 check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2938 // Actually *do* the STORE here
2939 if (host_is_little_endian()) {
2940 // FIXME: aren't we really concerned whether the guest
2941 // is little endian, not whether the host is?
2942 *(ULong*)(m + 0) = ls8B;
2943 *(ULong*)(m + 8) = ms8B;
2944 } else {
2945 *(ULong*)(m + 0) = ms8B;
2946 *(ULong*)(m + 8) = ls8B;
2947 }
2948 nonptr_or_unknown_range(m, 16);
2949}
2950
2951// This handles 128 bit stores on 64 bit targets. The
2952// store data is passed in 2 pieces, the most significant
2953// bits first.
2954static VG_REGPARM(3)
2955void check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg,
2956 UWord ms4B, UWord w2,
2957 UWord w1, UWord ls4B)
2958{
2959 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2960# if SC_SEGS
2961 checkSeg(mptr_vseg);
2962# endif
2963 check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2964 // Actually *do* the STORE here
2965 if (host_is_little_endian()) {
2966 // FIXME: aren't we really concerned whether the guest
2967 // is little endian, not whether the host is?
2968 *(UInt*)(m + 0) = ls4B;
2969 *(UInt*)(m + 4) = w1;
2970 *(UInt*)(m + 8) = w2;
2971 *(UInt*)(m + 12) = ms4B;
2972 } else {
2973 *(UInt*)(m + 0) = ms4B;
2974 *(UInt*)(m + 4) = w2;
2975 *(UInt*)(m + 8) = w1;
2976 *(UInt*)(m + 12) = ls4B;
2977 }
2978 nonptr_or_unknown_range(m, 16);
2979}
2980
2981// This handles 64 bit stores on 32 bit targets. The
2982// store data is passed in 2 pieces, the most significant
2983// bits first.
2984static VG_REGPARM(3)
2985void check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg,
2986 UWord ms4B, UWord ls4B)
2987{
2988 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2989# if SC_SEGS
2990 checkSeg(mptr_vseg);
2991# endif
2992 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
2993 // Actually *do* the STORE here
2994 if (host_is_little_endian()) {
2995 // FIXME: aren't we really concerned whether the guest
2996 // is little endian, not whether the host is?
2997 *(UInt*)(m + 0) = ls4B;
2998 *(UInt*)(m + 4) = ms4B;
2999 } else {
3000 *(UInt*)(m + 0) = ms4B;
3001 *(UInt*)(m + 4) = ls4B;
3002 }
3003 nonptr_or_unknown_range(m, 8);
3004}
3005
3006// This handles 64 bit non pointer stores on 64 bit targets.
3007// It must not be called on 32 bit targets.
3008static VG_REGPARM(3)
3009void check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B)
3010{
3011 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3012# if SC_SEGS
3013 checkSeg(mptr_vseg);
3014# endif
3015 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3016 // Actually *do* the STORE here
3017 *(ULong*)m = all8B;
3018 nonptr_or_unknown_range(m, 8);
3019}
3020
3021// This handles 64 bit stores on 64 bit targets. It must
3022// not be called on 32 bit targets.
3023static VG_REGPARM(3)
3024void check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3025{
3026 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3027# if SC_SEGS
3028 checkSeg(t_vseg);
3029 checkSeg(mptr_vseg);
3030# endif
3031 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3032 // Actually *do* the STORE here
3033 *(ULong*)m = t;
3034 if (VG_IS_8_ALIGNED(m)) {
3035 set_mem_vseg( m, t_vseg );
3036 } else {
3037 // straddling two words
3038 nonptr_or_unknown_range(m, 8);
3039 }
3040}
3041
3042// This handles 32 bit stores on 32 bit targets. It must
3043// not be called on 64 bit targets.
3044static VG_REGPARM(3)
3045void check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3046{
3047 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3048# if SC_SEGS
3049 checkSeg(t_vseg);
3050 checkSeg(mptr_vseg);
3051# endif
3052 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3053 // Actually *do* the STORE here
3054 *(UInt*)m = t;
3055 if (VG_IS_4_ALIGNED(m)) {
3056 set_mem_vseg( m, t_vseg );
3057 } else {
3058 // straddling two words
3059 nonptr_or_unknown_range(m, 4);
3060 }
3061}
3062
3063// Used for both 32 bit and 64 bit targets.
3064static VG_REGPARM(3)
3065void check_store4(Addr m, Seg* mptr_vseg, UWord t)
3066{
3067# if SC_SEGS
3068 checkSeg(mptr_vseg);
3069# endif
3070 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3071 // Actually *do* the STORE here (Nb: cast must be to 4-byte type!)
3072 *(UInt*)m = t;
3073 nonptr_or_unknown_range(m, 4);
3074}
3075
3076// Used for both 32 bit and 64 bit targets.
3077static VG_REGPARM(3)
3078void check_store2(Addr m, Seg* mptr_vseg, UWord t)
3079{
3080# if SC_SEGS
3081 checkSeg(mptr_vseg);
3082# endif
3083 check_load_or_store(/*is_write*/True, m, 2, mptr_vseg);
3084 // Actually *do* the STORE here (Nb: cast must be to 2-byte type!)
3085 *(UShort*)m = t;
3086 nonptr_or_unknown_range(m, 2);
3087}
3088
3089// Used for both 32 bit and 64 bit targets.
3090static VG_REGPARM(3)
3091void check_store1(Addr m, Seg* mptr_vseg, UWord t)
3092{
3093# if SC_SEGS
3094 checkSeg(mptr_vseg);
3095# endif
3096 check_load_or_store(/*is_write*/True, m, 1, mptr_vseg);
3097 // Actually *do* the STORE here (Nb: cast must be to 1-byte type!)
3098 *(UChar*)m = t;
3099 nonptr_or_unknown_range(m, 1);
3100}
3101
3102
3103// Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM
3104// be changed to NONPTR by a range check on the result.
3105#define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \
3106 if (BOTTOM == seg1 || BOTTOM == seg2) { bt; \
3107 } else if (NONPTR == seg1) { if (NONPTR == seg2) { nn; } \
3108 else if (UNKNOWN == seg2) { nu; } \
3109 else { np; } \
3110 } else if (UNKNOWN == seg1) { if (NONPTR == seg2) { un; } \
3111 else if (UNKNOWN == seg2) { uu; } \
3112 else { up; } \
3113 } else { if (NONPTR == seg2) { pn; } \
3114 else if (UNKNOWN == seg2) { pu; } \
3115 else { pp; } \
3116 }
3117
3118#define BINERROR(opname) \
3119 h_record_arith_error(seg1, seg2, opname); \
3120 out = NONPTR
3121
3122
3123// -------------
3124// + | n ? p
3125// -------------
3126// n | n ? p
3127// ? | ? ? ?
3128// p | p ? e (all results become n if they look like a non-pointer)
3129// -------------
3130static Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname)
3131{
3132 Seg* out;
3133# if SC_SEGS
3134 checkSeg(seg1);
3135 checkSeg(seg2);
3136# endif
3137 BINOP(
3138 return BOTTOM,
3139 out = NONPTR, out = UNKNOWN, out = seg2,
3140 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3141 out = seg1, out = UNKNOWN, BINERROR(opname)
3142 );
3143 return ( looks_like_a_pointer(result) ? out : NONPTR );
3144}
3145
3146static VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result)
3147{
3148 Seg* out;
3149# if SC_SEGS
3150 checkSeg(seg1);
3151 checkSeg(seg2);
3152# endif
3153 out = do_addW_result(seg1, seg2, result, "Add32/Add64");
3154# if SC_SEGS
3155 checkSeg(out);
3156# endif
3157 return out;
3158}
3159
3160// -------------
3161// - | n ? p (Nb: operation is seg1 - seg2)
3162// -------------
3163// n | n ? n+ (+) happens a lot due to "cmp", but result should never
3164// ? | ? ? n/B be used, so give 'n'
3165// p | p p? n*/B (*) and possibly link the segments
3166// -------------
3167static VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result)
3168{
3169 Seg* out;
3170# if SC_SEGS
3171 checkSeg(seg1);
3172 checkSeg(seg2);
3173# endif
3174 // Nb: when returning BOTTOM, don't let it go through the range-check;
3175 // a segment linking offset can easily look like a nonptr.
3176 BINOP(
3177 return BOTTOM,
3178 out = NONPTR, out = UNKNOWN, out = NONPTR,
3179 out = UNKNOWN, out = UNKNOWN, return BOTTOM,
3180 out = seg1, out = seg1/*??*/, return BOTTOM
3181 );
3182 #if 0
3183 // This is for the p-p segment-linking case
3184 Seg end2 = seg2;
3185 while (end2->links != seg2) end2 = end2->links;
3186 end2->links = seg1->links;
3187 seg1->links = seg2;
3188 return NONPTR;
3189 #endif
3190 return ( looks_like_a_pointer(result) ? out : NONPTR );
3191}
3192
3193// -------------
3194// & | n ? p
3195// -------------
3196// n | n ? p
3197// ? | ? ? ?
3198// p | p ? * (*) if p1==p2 then p else e (see comment)
3199// -------------
3200/* Seems to be OK to And two pointers:
3201 testq %ptr1,%ptr2
3202 jnz ..
3203 which possibly derives from
3204 if (ptr1 & ptr2) { A } else { B }
3205 not sure what that means
3206*/
3207static VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2,
3208 UWord result, UWord args_diff)
3209{
3210 Seg* out;
3211 if (0 == args_diff) {
3212 // p1==p2
3213 out = seg1;
3214 } else {
3215 BINOP(
3216 return BOTTOM,
3217 out = NONPTR, out = UNKNOWN, out = seg2,
3218 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3219 out = seg1, out = UNKNOWN, out = NONPTR
3220 /*BINERROR("And32/And64")*/
3221 );
3222 }
3223 out = ( looks_like_a_pointer(result) ? out : NONPTR );
3224 return out;
3225}
3226
3227// -------------
3228// `|`| n ? p
3229// -------------
3230// n | n ? p
3231// ? | ? ? ?
3232// p | p ? n
3233// -------------
3234/* It's OK to Or two pointers together, but the result definitely
3235 isn't a pointer. Why would you want to do that? Because of this:
3236 char* p1 = malloc(..);
3237 char* p2 = malloc(..);
3238 ...
3239 if (p1 || p2) { .. }
3240 In this case gcc on x86/amd64 quite literally or-s the two pointers
3241 together and throws away the result, the purpose of which is merely
3242 to sets %eflags.Z/%rflags.Z. So we have to allow it.
3243*/
3244static VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result)
3245{
3246 Seg* out;
3247 BINOP(
3248 return BOTTOM,
3249 out = NONPTR, out = UNKNOWN, out = seg2,
3250 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3251 out = seg1, out = UNKNOWN, out = NONPTR
3252 );
3253 out = ( looks_like_a_pointer(result) ? out : NONPTR );
3254 return out;
3255}
3256
3257// -------------
3258// ~ | n ? p
3259// -------------
3260// | n n n
3261// -------------
3262static VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result)
3263{
3264# if SC_SEGS
3265 checkSeg(seg1);
3266# endif
3267 if (BOTTOM == seg1) return BOTTOM;
3268 return NONPTR;
3269}
3270
3271// Pointers are rarely multiplied, but sometimes legitimately, eg. as hash
3272// function inputs. But two pointers args --> error.
3273// Pretend it always returns a nonptr. Maybe improve later.
3274static VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2)
3275{
3276# if SC_SEGS
3277 checkSeg(seg1);
3278 checkSeg(seg2);
3279# endif
3280 if (is_known_segment(seg1) && is_known_segment(seg2))
3281 h_record_arith_error(seg1, seg2, "Mul32/Mul64");
3282 return NONPTR;
3283}
3284
3285
3286/*--------------------------------------------------------------------*/
3287/*--- Instrumentation ---*/
3288/*--------------------------------------------------------------------*/
3289
3290/* The h_ instrumenter that follows is complex, since it deals with
3291 shadow value computation.
3292
3293 It also needs to generate instrumentation for the sg_ side of
3294 things. That's relatively straightforward. However, rather than
3295 confuse the code herein any further, we simply delegate the problem
3296 to sg_main.c, by using the four functions
3297 sg_instrument_{init,fini,IRStmt,final_jump}. These four completely
3298 abstractify the sg_ instrumentation. See comments in sg_main.c's
3299 instrumentation section for further details. */
3300
3301/* Carries around state during Ptrcheck instrumentation. */
3302typedef
3303 struct {
3304 /* MODIFIED: the superblock being constructed. IRStmts are
3305 added. */
3306 IRSB* bb;
3307 Bool trace;
3308
3309 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
3310 original temps to their current their current shadow temp.
3311 Initially all entries are IRTemp_INVALID. Entries are added
3312 lazily since many original temps are not used due to
3313 optimisation prior to instrumentation. Note that only
3314 integer temps of the guest word size are shadowed, since it
3315 is impossible (or meaningless) to hold a pointer in any other
3316 type of temp. */
3317 IRTemp* tmpMap;
3318 Int n_originalTmps; /* for range checking */
3319
3320 /* READONLY: the host word type. Needed for constructing
3321 arguments of type 'HWord' to be passed to helper functions.
3322 Ity_I32 or Ity_I64 only. */
3323 IRType hWordTy;
3324
3325 /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
3326 IRType gWordTy;
3327
3328 /* READONLY: the guest state size, so we can generate shadow
3329 offsets correctly. */
3330 Int guest_state_sizeB;
3331 }
3332 PCEnv;
3333
3334/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
3335 demand), as they are encountered. This is for two reasons.
3336
3337 (1) (less important reason): Many original tmps are unused due to
3338 initial IR optimisation, and we do not want to spaces in tables
3339 tracking them.
3340
3341 Shadow IRTemps are therefore allocated on demand. pce.tmpMap is a
3342 table indexed [0 .. n_types-1], which gives the current shadow for
3343 each original tmp, or INVALID_IRTEMP if none is so far assigned.
3344 It is necessary to support making multiple assignments to a shadow
3345 -- specifically, after testing a shadow for definedness, it needs
3346 to be made defined. But IR's SSA property disallows this.
3347
3348 (2) (more important reason): Therefore, when a shadow needs to get
3349 a new value, a new temporary is created, the value is assigned to
3350 that, and the tmpMap is updated to reflect the new binding.
3351
3352 A corollary is that if the tmpMap maps a given tmp to
3353 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
3354 there's a read-before-write error in the original tmps. The IR
3355 sanity checker should catch all such anomalies, however.
3356*/
3357
3358/* Find the tmp currently shadowing the given original tmp. If none
3359 so far exists, allocate one. */
3360static IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig )
3361{
3362 tl_assert(orig < pce->n_originalTmps);
3363 tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3364 if (pce->tmpMap[orig] == IRTemp_INVALID) {
3365 tl_assert(0);
3366 pce->tmpMap[orig]
3367 = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3368 }
3369 return pce->tmpMap[orig];
3370}
3371
3372/* Allocate a new shadow for the given original tmp. This means any
3373 previous shadow is abandoned. This is needed because it is
3374 necessary to give a new value to a shadow once it has been tested
3375 for undefinedness, but unfortunately IR's SSA property disallows
3376 this. Instead we must abandon the old shadow, allocate a new one
3377 and use that instead. */
3378__attribute__((noinline))
3379static IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig )
3380{
3381 tl_assert(orig < pce->n_originalTmps);
3382 tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3383 pce->tmpMap[orig]
3384 = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3385 return pce->tmpMap[orig];
3386}
3387
3388
3389/*------------------------------------------------------------*/
3390/*--- IRAtoms -- a subset of IRExprs ---*/
3391/*------------------------------------------------------------*/
3392
3393/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
3394 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
3395 input, most of this code deals in atoms. Usefully, a value atom
3396 always has a V-value which is also an atom: constants are shadowed
3397 by constants, and temps are shadowed by the corresponding shadow
3398 temporary. */
3399
3400typedef IRExpr IRAtom;
3401
3402//zz /* (used for sanity checks only): is this an atom which looks
3403//zz like it's from original code? */
3404//zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 )
3405//zz {
3406//zz if (a1->tag == Iex_Const)
3407//zz return True;
3408//zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps)
3409//zz return True;
3410//zz return False;
3411//zz }
3412//zz
3413//zz /* (used for sanity checks only): is this an atom which looks
3414//zz like it's from shadow code? */
3415//zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 )
3416//zz {
3417//zz if (a1->tag == Iex_Const)
3418//zz return True;
3419//zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps)
3420//zz return True;
3421//zz return False;
3422//zz }
3423//zz
3424//zz /* (used for sanity checks only): check that both args are atoms and
3425//zz are identically-kinded. */
3426//zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
3427//zz {
3428//zz if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
3429//zz return True;
3430//zz if (a1->tag == Iex_Const && a2->tag == Iex_Const)
3431//zz return True;
3432//zz return False;
3433//zz }
3434
3435
3436/*------------------------------------------------------------*/
3437/*--- Constructing IR fragments ---*/
3438/*------------------------------------------------------------*/
3439
3440/* add stmt to a bb */
3441static inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
3442 if (pce->trace) {
3443 VG_(printf)(" %c: ", cat);
3444 ppIRStmt(st);
3445 VG_(printf)("\n");
3446 }
3447 addStmtToIRSB(pce->bb, st);
3448}
3449
3450/* assign value to tmp */
3451static inline
3452void assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) {
3453 stmt(cat, pce, IRStmt_WrTmp(tmp,expr));
3454}
3455
3456/* build various kinds of expressions */
3457#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
3458#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
3459#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
3460#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
3461#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
3462#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
3463#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
3464#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
3465
3466/* Bind the given expression to a new temporary, and return the
3467 temporary. This effectively converts an arbitrary expression into
3468 an atom.
3469
3470 'ty' is the type of 'e' and hence the type that the new temporary
3471 needs to be. But passing it is redundant, since we can deduce the
3472 type merely by inspecting 'e'. So at least that fact to assert
3473 that the two types agree. */
3474static IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) {
3475 IRTemp t;
3476 IRType tyE = typeOfIRExpr(pce->bb->tyenv, e);
3477 tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
3478 t = newIRTemp(pce->bb->tyenv, ty);
3479 assign(cat, pce, t, e);
3480 return mkexpr(t);
3481}
3482
3483
3484
3485//-----------------------------------------------------------------------
3486// Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows.
3487//
3488// Range check (NONPTR/seg):
3489// - after modifying a word-sized value in/into a TempReg:
3490// - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L
3491// - BSWAP
3492//
3493// Range check (NONPTR/UNKNOWN):
3494// - when introducing a new word-sized value into a TempReg:
3495// - MOVL l, t2
3496//
3497// - when copying a word-sized value which lacks a corresponding segment
3498// into a TempReg:
3499// - straddled LDL
3500//
3501// - when a sub-word of a word (or two) is updated:
3502// - SHROTL
3503// - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB]
3504// - PUT[WB]
3505// - straddled STL (2 range checks)
3506// - straddled STW (2 range checks)
3507// - unstraddled STW
3508// - STB
3509//
3510// Just copy:
3511// - when copying word-sized values:
3512// - MOVL t1, t2 (--optimise=no only)
3513// - CMOV
3514// - GETL, PUTL
3515// - unstraddled LDL, unstraddled STL
3516//
3517// - when barely changing
3518// - INC[LWB]/DEC[LWB]
3519//
3520// Set to NONPTR:
3521// - after copying a sub-word value into a TempReg:
3522// - MOV[WB] l, t2
3523// - GET[WB]
3524// - unstraddled LDW
3525// - straddled LDW
3526// - LDB
3527// - POP[WB]
3528//
3529// - after copying an obvious non-ptr into a TempReg:
3530// - GETF
3531// - CC2VAL
3532// - POPL
3533//
3534// - after copying an obvious non-ptr into a memory word:
3535// - FPU_W
3536//
3537// Do nothing:
3538// - LOCK, INCEIP
3539// - WIDEN[WB]
3540// - JMP, JIFZ
3541// - CALLM_[SE], PUSHL, CALLM, CLEAR
3542// - FPU, FPU_R (and similar MMX/SSE ones)
3543//
3544
3545
3546
3547
3548/* Call h_fn (name h_nm) with the given arg, and return a new IRTemp
3549 holding the result. The arg must be a word-typed atom. Callee
3550 must be a VG_REGPARM(1) function. */
3551__attribute__((noinline))
3552static IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3553 IRExpr* a1 )
3554{
3555 IRTemp res;
3556 IRDirty* di;
3557 tl_assert(isIRAtom(a1));
3558 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3559 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3560 di = unsafeIRDirty_1_N( res, 1/*regparms*/,
3561 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3562 mkIRExprVec_1( a1 ) );
3563 stmt( 'I', pce, IRStmt_Dirty(di) );
3564 return res;
3565}
3566
3567/* Two-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(2)
3568 function.*/
3569static IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3570 IRExpr* a1, IRExpr* a2 )
3571{
3572 IRTemp res;
3573 IRDirty* di;
3574 tl_assert(isIRAtom(a1));
3575 tl_assert(isIRAtom(a2));
3576 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3577 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3578 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3579 di = unsafeIRDirty_1_N( res, 2/*regparms*/,
3580 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3581 mkIRExprVec_2( a1, a2 ) );
3582 stmt( 'I', pce, IRStmt_Dirty(di) );
3583 return res;
3584}
3585
3586/* Three-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3)
3587 function.*/
3588static IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3589 IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3590{
3591 IRTemp res;
3592 IRDirty* di;
3593 tl_assert(isIRAtom(a1));
3594 tl_assert(isIRAtom(a2));
3595 tl_assert(isIRAtom(a3));
3596 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3597 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3598 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3599 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3600 di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3601 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3602 mkIRExprVec_3( a1, a2, a3 ) );
3603 stmt( 'I', pce, IRStmt_Dirty(di) );
3604 return res;
3605}
3606
3607/* Four-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3)
3608 function.*/
3609static IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3610 IRExpr* a1, IRExpr* a2,
3611 IRExpr* a3, IRExpr* a4 )
3612{
3613 IRTemp res;
3614 IRDirty* di;
3615 tl_assert(isIRAtom(a1));
3616 tl_assert(isIRAtom(a2));
3617 tl_assert(isIRAtom(a3));
3618 tl_assert(isIRAtom(a4));
3619 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3620 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3621 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3622 tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3623 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3624 di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3625 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3626 mkIRExprVec_4( a1, a2, a3, a4 ) );
3627 stmt( 'I', pce, IRStmt_Dirty(di) );
3628 return res;
3629}
3630
3631/* Version of gen_dirty_W_WW with no return value. Callee must be a
3632 VG_REGPARM(2) function.*/
3633static void gen_dirty_v_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3634 IRExpr* a1, IRExpr* a2 )
3635{
3636 IRDirty* di;
3637 tl_assert(isIRAtom(a1));
3638 tl_assert(isIRAtom(a2));
3639 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3640 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3641 di = unsafeIRDirty_0_N( 2/*regparms*/,
3642 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3643 mkIRExprVec_2( a1, a2 ) );
3644 stmt( 'I', pce, IRStmt_Dirty(di) );
3645}
3646
3647/* Version of gen_dirty_W_WWW with no return value. Callee must be a
3648 VG_REGPARM(3) function.*/
3649static void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3650 IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3651{
3652 IRDirty* di;
3653 tl_assert(isIRAtom(a1));
3654 tl_assert(isIRAtom(a2));
3655 tl_assert(isIRAtom(a3));
3656 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3657 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3658 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3659 di = unsafeIRDirty_0_N( 3/*regparms*/,
3660 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3661 mkIRExprVec_3( a1, a2, a3 ) );
3662 stmt( 'I', pce, IRStmt_Dirty(di) );
3663}
3664
3665/* Version of gen_dirty_v_WWW for 4 arguments. Callee must be a
3666 VG_REGPARM(3) function.*/
3667static void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3668 IRExpr* a1, IRExpr* a2,
3669 IRExpr* a3, IRExpr* a4 )
3670{
3671 IRDirty* di;
3672 tl_assert(isIRAtom(a1));
3673 tl_assert(isIRAtom(a2));
3674 tl_assert(isIRAtom(a3));
3675 tl_assert(isIRAtom(a4));
3676 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3677 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3678 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3679 tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3680 di = unsafeIRDirty_0_N( 3/*regparms*/,
3681 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3682 mkIRExprVec_4( a1, a2, a3, a4 ) );
3683 stmt( 'I', pce, IRStmt_Dirty(di) );
3684}
3685
3686/* Version of gen_dirty_v_WWW for 6 arguments. Callee must be a
3687 VG_REGPARM(3) function.*/
3688static void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3689 IRExpr* a1, IRExpr* a2, IRExpr* a3,
3690 IRExpr* a4, IRExpr* a5, IRExpr* a6 )
3691{
3692 IRDirty* di;
3693 tl_assert(isIRAtom(a1));
3694 tl_assert(isIRAtom(a2));
3695 tl_assert(isIRAtom(a3));
3696 tl_assert(isIRAtom(a4));
3697 tl_assert(isIRAtom(a5));
3698 tl_assert(isIRAtom(a6));
3699 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3700 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3701 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3702 tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3703 tl_assert(typeOfIRExpr(pce->bb->tyenv, a5) == pce->gWordTy);
3704 tl_assert(typeOfIRExpr(pce->bb->tyenv, a6) == pce->gWordTy);
3705 di = unsafeIRDirty_0_N( 3/*regparms*/,
3706 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3707 mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) );
3708 stmt( 'I', pce, IRStmt_Dirty(di) );
3709}
3710
3711static IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a )
3712{
3713 IRType a_ty = typeOfIRExpr(pce->bb->tyenv, a);
3714 tl_assert(isIRAtom(a));
3715 if (pce->hWordTy == Ity_I32) {
3716 switch (a_ty) {
3717 case Ity_I8:
3718 return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) );
3719 case Ity_I16:
3720 return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) );
3721 default:
3722 ppIRType(a_ty);
3723 tl_assert(0);
3724 }
3725 } else {
3726 tl_assert(pce->hWordTy == Ity_I64);
3727 switch (a_ty) {
3728 case Ity_I8:
3729 return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) );
3730 case Ity_I16:
3731 return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) );
3732 case Ity_I32:
3733 return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) );
3734 default:
3735 ppIRType(a_ty);
3736 tl_assert(0);
3737 }
3738 }
3739}
3740
3741/* 'e' is a word-sized atom. Call nonptr_or_unknown with it, bind the
3742 results to a new temporary, and return the temporary. Note this
3743 takes an original expression but returns a shadow value. */
3744static IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e )
3745{
3746 return gen_dirty_W_W( pce, &nonptr_or_unknown,
3747 "nonptr_or_unknown", e );
3748}
3749
3750
3751/* Generate the shadow value for an IRExpr which is an atom and
3752 guaranteed to be word-sized. */
3753static IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e )
3754{
3755 if (pce->gWordTy == Ity_I32) {
3756 if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) {
3757 IRTemp t;
3758 tl_assert(sizeof(UWord) == 4);
3759 t = gen_call_nonptr_or_unknown_w(pce, e);
3760 return mkexpr(t);
3761 }
3762 if (e->tag == Iex_RdTmp
3763 && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I32) {
3764 return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3765 }
3766 /* there are no other word-sized atom cases */
3767 } else {
3768 if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) {
3769 IRTemp t;
3770 tl_assert(sizeof(UWord) == 8);
3771 //return mkU64( (ULong)(UWord)NONPTR );
3772 t = gen_call_nonptr_or_unknown_w(pce, e);
3773 return mkexpr(t);
3774 }
3775 if (e->tag == Iex_RdTmp
3776 && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I64) {
3777 return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3778 }
3779 /* there are no other word-sized atom cases */
3780 }
3781 ppIRExpr(e);
3782 tl_assert(0);
3783}
3784
3785
3786static
3787void instrument_arithop ( PCEnv* pce,
3788 IRTemp dst, /* already holds result */
3789 IRTemp dstv, /* generate an assignment to this */
3790 IROp op,
3791 /* original args, guaranteed to be atoms */
3792 IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 )
3793{
3794 HChar* nm = NULL;
3795 void* fn = NULL;
3796 IRExpr* a1v = NULL;
3797 IRExpr* a2v = NULL;
3798 //IRExpr* a3v = NULL;
3799 //IRExpr* a4v = NULL;
3800 IRTemp res = IRTemp_INVALID;
3801
3802 if (pce->gWordTy == Ity_I32) {
3803
3804 tl_assert(pce->hWordTy == Ity_I32);
3805 switch (op) {
3806
3807 /* For these cases, pass Segs for both arguments, and the
3808 result value. */
3809 case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32;
3810 case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32;
3811 case Iop_Or32: nm = "do_orW"; fn = &do_orW; goto ssr32;
3812 ssr32:
3813 a1v = schemeEw_Atom( pce, a1 );
3814 a2v = schemeEw_Atom( pce, a2 );
3815 res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3816 assign( 'I', pce, dstv, mkexpr(res) );
3817 break;
3818
3819 /* In this case, pass Segs for both arguments, the result
3820 value, and the difference between the (original) values of
3821 the arguments. */
3822 case Iop_And32:
3823 nm = "do_andW"; fn = &do_andW;
3824 a1v = schemeEw_Atom( pce, a1 );
3825 a2v = schemeEw_Atom( pce, a2 );
3826 res = gen_dirty_W_WWWW(
3827 pce, fn, nm, a1v, a2v, mkexpr(dst),
3828 assignNew( 'I', pce, Ity_I32,
3829 binop(Iop_Sub32,a1,a2) ) );
3830 assign( 'I', pce, dstv, mkexpr(res) );
3831 break;
3832
3833 /* Pass one shadow arg and the result to the helper. */
3834 case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32;
3835 vr32:
3836 a1v = schemeEw_Atom( pce, a1 );
3837 res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3838 assign( 'I', pce, dstv, mkexpr(res) );
3839 break;
3840
3841 /* Pass two shadow args only to the helper. */
3842 case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32;
3843 vv32:
3844 a1v = schemeEw_Atom( pce, a1 );
3845 a2v = schemeEw_Atom( pce, a2 );
3846 res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3847 assign( 'I', pce, dstv, mkexpr(res) );
3848 break;
3849
3850 /* We don't really know what the result could be; test at run
3851 time. */
3852 case Iop_64HIto32: goto n_or_u_32;
3853 case Iop_64to32: goto n_or_u_32;
3854 case Iop_Xor32: goto n_or_u_32;
3855 n_or_u_32:
3856 assign( 'I', pce, dstv,
3857 mkexpr(
3858 gen_call_nonptr_or_unknown_w( pce,
3859 mkexpr(dst) ) ) );
3860 break;
3861
3862 /* Cases where it's very obvious that the result cannot be a
3863 pointer. Hence declare directly that it's NONPTR; don't
3864 bother with the overhead of calling nonptr_or_unknown. */
3865
3866 /* cases where it makes no sense for the result to be a ptr */
3867 /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3868 arg, so that shift by zero preserves the original
3869 value. */
3870 case Iop_Shl32: goto n32;
3871 case Iop_Sar32: goto n32;
3872 case Iop_Shr32: goto n32;
3873 case Iop_16Uto32: goto n32;
3874 case Iop_16Sto32: goto n32;
3875 case Iop_F64toI32: goto n32;
3876 case Iop_16HLto32: goto n32;
3877 case Iop_MullS16: goto n32;
3878 case Iop_MullU16: goto n32;
3879 case Iop_PRemC3210F64: goto n32;
3880 case Iop_DivU32: goto n32;
3881 case Iop_DivS32: goto n32;
3882 case Iop_V128to32: goto n32;
3883
3884 /* cases where result range is very limited and clearly cannot
3885 be a pointer */
3886 case Iop_1Uto32: goto n32;
3887 case Iop_1Sto32: goto n32;
3888 case Iop_8Uto32: goto n32;
3889 case Iop_8Sto32: goto n32;
3890 case Iop_Clz32: goto n32;
3891 case Iop_Ctz32: goto n32;
3892 case Iop_CmpF64: goto n32;
3893 case Iop_CmpORD32S: goto n32;
3894 case Iop_CmpORD32U: goto n32;
3895 n32:
3896 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
3897 break;
3898
3899 default:
3900 VG_(printf)("instrument_arithop(32-bit): unhandled: ");
3901 ppIROp(op);
3902 tl_assert(0);
3903 }
3904
3905 } else {
3906
3907 tl_assert(pce->gWordTy == Ity_I64);
3908 switch (op) {
3909
3910 /* For these cases, pass Segs for both arguments, and the
3911 result value. */
3912 case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64;
3913 case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64;
3914 case Iop_Or64: nm = "do_orW"; fn = &do_orW; goto ssr64;
3915 ssr64:
3916 a1v = schemeEw_Atom( pce, a1 );
3917 a2v = schemeEw_Atom( pce, a2 );
3918 res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3919 assign( 'I', pce, dstv, mkexpr(res) );
3920 break;
3921
3922 /* In this case, pass Segs for both arguments, the result
3923 value, and the difference between the (original) values of
3924 the arguments. */
3925 case Iop_And64:
3926 nm = "do_andW"; fn = &do_andW;
3927 a1v = schemeEw_Atom( pce, a1 );
3928 a2v = schemeEw_Atom( pce, a2 );
3929 res = gen_dirty_W_WWWW(
3930 pce, fn, nm, a1v, a2v, mkexpr(dst),
3931 assignNew( 'I', pce, Ity_I64,
3932 binop(Iop_Sub64,a1,a2) ) );
3933 assign( 'I', pce, dstv, mkexpr(res) );
3934 break;
3935
3936 /* Pass one shadow arg and the result to the helper. */
3937 case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64;
3938 vr64:
3939 a1v = schemeEw_Atom( pce, a1 );
3940 res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3941 assign( 'I', pce, dstv, mkexpr(res) );
3942 break;
3943
3944 /* Pass two shadow args only to the helper. */
3945 case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64;
3946 vv64:
3947 a1v = schemeEw_Atom( pce, a1 );
3948 a2v = schemeEw_Atom( pce, a2 );
3949 res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3950 assign( 'I', pce, dstv, mkexpr(res) );
3951 break;
3952
3953 /* We don't really know what the result could be; test at run
3954 time. */
3955 case Iop_Xor64: goto n_or_u_64;
3956 case Iop_128HIto64: goto n_or_u_64;
3957 case Iop_128to64: goto n_or_u_64;
3958 case Iop_V128HIto64: goto n_or_u_64;
3959 case Iop_V128to64: goto n_or_u_64;
3960 n_or_u_64:
3961 assign( 'I', pce, dstv,
3962 mkexpr(
3963 gen_call_nonptr_or_unknown_w( pce,
3964 mkexpr(dst) ) ) );
3965 break;
3966
3967 /* Cases where it's very obvious that the result cannot be a
3968 pointer. Hence declare directly that it's NONPTR; don't
3969 bother with the overhead of calling nonptr_or_unknown. */
3970
3971 /* cases where it makes no sense for the result to be a ptr */
3972 /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3973 arg, so that shift by zero preserves the original
3974 value. */
3975 case Iop_Shl64: goto n64;
3976 case Iop_Sar64: goto n64;
3977 case Iop_Shr64: goto n64;
3978 case Iop_32Uto64: goto n64;
3979 case Iop_32Sto64: goto n64;
3980 case Iop_16Uto64: goto n64;
3981 case Iop_16Sto64: goto n64;
3982 case Iop_32HLto64: goto n64;
3983 case Iop_DivModU64to32: goto n64;
3984 case Iop_DivModS64to32: goto n64;
3985 case Iop_F64toI64: goto n64;
3986 case Iop_MullS32: goto n64;
3987 case Iop_MullU32: goto n64;
3988 case Iop_DivU64: goto n64;
3989 case Iop_DivS64: goto n64;
3990 case Iop_ReinterpF64asI64: goto n64;
3991
3992 /* cases where result range is very limited and clearly cannot
3993 be a pointer */
3994 case Iop_1Uto64: goto n64;
3995 case Iop_8Uto64: goto n64;
3996 case Iop_8Sto64: goto n64;
3997 case Iop_Ctz64: goto n64;
3998 case Iop_Clz64: goto n64;
3999 case Iop_CmpORD64S: goto n64;
4000 case Iop_CmpORD64U: goto n64;
4001 /* 64-bit simd */
4002 case Iop_Avg8Ux8: case Iop_Avg16Ux4:
4003 case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4:
4004 case Iop_Min8Ux8: case Iop_MulHi16Ux4:
4005 case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4:
4006 case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2:
4007 case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8:
4008 case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8:
4009 case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8:
4010 case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4:
4011 case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4:
4012 case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2:
4013 case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2:
4014 case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8:
4015 case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8:
4016 case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4:
4017 case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2:
4018 case Iop_InterleaveLO16x4: case Iop_SarN8x8:
4019 case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2:
4020 case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4:
4021 n64:
4022 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4023 break;
4024
4025 default:
4026 VG_(printf)("instrument_arithop(64-bit): unhandled: ");
4027 ppIROp(op);
4028 tl_assert(0);
4029 }
4030 }
4031}
4032
4033static
4034void gen_call_nonptr_or_unknown_range ( PCEnv* pce,
4035 IRAtom* addr, IRAtom* len )
4036{
4037 gen_dirty_v_WW( pce,
4038 &nonptr_or_unknown_range,
4039 "nonptr_or_unknown_range",
4040 addr, len );
4041}
4042
4043/* iii describes zero or more non-exact integer register updates. For
4044 each one, generate IR to get the containing register, apply
4045 nonptr_or_unknown to it, and write it back again. */
4046static void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii )
4047{
4048 Int i;
4049 tl_assert(iii && iii->n_offsets >= 0);
4050 for (i = 0; i < iii->n_offsets; i++) {
4051 IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy,
4052 IRExpr_Get( iii->offsets[i], pce->gWordTy ));
4053 IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4054 stmt( 'I', pce, IRStmt_Put( iii->offsets[i]
4055 + pce->guest_state_sizeB,
4056 mkexpr(a2) ));
4057 }
4058}
4059
4060/* Generate into 'ane', instrumentation for 'st'. Also copy 'st'
4061 itself into 'ane' (the caller does not do so). This is somewhat
4062 complex and relies heavily on the assumption that the incoming IR
4063 is in flat form.
4064
4065 Generally speaking, the instrumentation is placed after the
4066 original statement, so that results computed by the original can be
4067 used in the instrumentation. However, that isn't safe for memory
4068 references, since we need the instrumentation (hence bounds check
4069 and potential error message) to happen before the reference itself,
4070 as the latter could cause a fault. */
4071static void schemeS ( PCEnv* pce, IRStmt* st )
4072{
4073 tl_assert(st);
4074 tl_assert(isFlatIRStmt(st));
4075
4076 switch (st->tag) {
4077
4078 case Ist_Dirty: {
4079 Int i;
4080 IRDirty* di;
4081 stmt( 'C', pce, st );
4082 /* nasty. assumes that (1) all helpers are unconditional,
4083 and (2) all outputs are non-ptr */
4084 di = st->Ist.Dirty.details;
4085 /* deal with the return tmp, if any */
4086 if (di->tmp != IRTemp_INVALID
4087 && typeOfIRTemp(pce->bb->tyenv, di->tmp) == pce->gWordTy) {
4088 /* di->tmp is shadowed. Set it to NONPTR. */
4089 IRTemp dstv = newShadowTmp( pce, di->tmp );
4090 if (pce->gWordTy == Ity_I32) {
4091 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4092 } else {
4093 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4094 }
4095 }
4096 /* apply the nonptr_or_unknown technique to any parts of
4097 the guest state that happen to get written */
4098 for (i = 0; i < di->nFxState; i++) {
4099 IntRegInfo iii;
4100 tl_assert(di->fxState[i].fx != Ifx_None);
4101 if (di->fxState[i].fx == Ifx_Read)
4102 continue; /* this bit is only read -- not interesting */
4103 get_IntRegInfo( &iii, di->fxState[i].offset,
4104 di->fxState[i].size );
4105 tl_assert(iii.n_offsets >= -1
4106 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4107 /* Deal with 3 possible cases, same as with Ist_Put
4108 elsewhere in this function. */
4109 if (iii.n_offsets == -1) {
4110 /* case (1): exact write of an integer register. */
4111 IRAtom* a1
4112 = assignNew( 'I', pce, pce->gWordTy,
4113 IRExpr_Get( iii.offsets[i], pce->gWordTy ));
4114 IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4115 stmt( 'I', pce, IRStmt_Put( iii.offsets[i]
4116 + pce->guest_state_sizeB,
4117 mkexpr(a2) ));
4118 } else {
4119 /* when == 0: case (3): no instrumentation needed */
4120 /* when > 0: case (2) .. complex case. Fish out the
4121 stored value for the whole register, heave it
4122 through nonptr_or_unknown, and use that as the new
4123 shadow value. */
4124 tl_assert(iii.n_offsets >= 0
4125 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4126 gen_nonptr_or_unknown_for_III( pce, &iii );
4127 }
4128 } /* for (i = 0; i < di->nFxState; i++) */
4129 /* finally, deal with memory outputs */
4130 if (di->mFx != Ifx_None) {
4131 tl_assert(di->mAddr && isIRAtom(di->mAddr));
4132 tl_assert(di->mSize > 0);
4133 gen_call_nonptr_or_unknown_range( pce, di->mAddr,
4134 mkIRExpr_HWord(di->mSize));
4135 }
4136 break;
4137 }
4138
4139 case Ist_NoOp:
4140 break;
4141
4142 /* nothing interesting in these; just copy them through */
4143 case Ist_AbiHint:
4144 case Ist_MBE:
4145 case Ist_Exit:
4146 case Ist_IMark:
4147 stmt( 'C', pce, st );
4148 break;
4149
4150 case Ist_PutI: {
4151 IRRegArray* descr = st->Ist.PutI.descr;
4152 stmt( 'C', pce, st );
4153 tl_assert(descr && descr->elemTy);
4154 if (is_integer_guest_reg_array(descr)) {
4155 /* if this fails, is_integer_guest_reg_array is returning
4156 bogus results */
4157 tl_assert(descr->elemTy == pce->gWordTy);
4158 stmt(
4159 'I', pce,
4160 IRStmt_PutI(
4161 mkIRRegArray(descr->base + pce->guest_state_sizeB,
4162 descr->elemTy, descr->nElems),
4163 st->Ist.PutI.ix,
4164 st->Ist.PutI.bias,
4165 schemeEw_Atom( pce, st->Ist.PutI.data)
4166 )
4167 );
4168 }
4169 break;
4170 }
4171
4172 case Ist_Put: {
4173 /* PUT(offset) = atom */
4174 /* 3 cases:
4175 1. It's a complete write of an integer register. Get hold of
4176 'atom's shadow value and write it in the shadow state.
4177 2. It's a partial write of an integer register. Let the write
4178 happen, then fish out the complete register value and see if,
4179 via range checking, consultation of tea leaves, etc, its
4180 shadow value can be upgraded to anything useful.
4181 3. It is none of the above. Generate no instrumentation. */
4182 IntRegInfo iii;
4183 IRType ty;
4184 stmt( 'C', pce, st );
4185 ty = typeOfIRExpr(pce->bb->tyenv, st->Ist.Put.data);
4186 get_IntRegInfo( &iii, st->Ist.Put.offset,
4187 sizeofIRType(ty) );
4188 if (iii.n_offsets == -1) {
4189 /* case (1): exact write of an integer register. */
4190 tl_assert(ty == pce->gWordTy);
4191 stmt( 'I', pce,
4192 IRStmt_Put( st->Ist.Put.offset
4193 + pce->guest_state_sizeB,
4194 schemeEw_Atom( pce, st->Ist.Put.data)) );
4195 } else {
4196 /* when == 0: case (3): no instrumentation needed */
4197 /* when > 0: case (2) .. complex case. Fish out the
4198 stored value for the whole register, heave it through
4199 nonptr_or_unknown, and use that as the new shadow
4200 value. */
4201 tl_assert(iii.n_offsets >= 0
4202 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4203 gen_nonptr_or_unknown_for_III( pce, &iii );
4204 }
4205 break;
4206 } /* case Ist_Put */
4207
4208 case Ist_Store: {
4209 /* We have: STle(addr) = data
4210 if data is int-word sized, do
4211 check_store4(addr, addr#, data, data#)
4212 for all other stores
4213 check_store{1,2}(addr, addr#, data)
4214
4215 The helper actually *does* the store, so that it can do
4216 the post-hoc ugly hack of inspecting and "improving" the
4217 shadow data after the store, in the case where it isn't an
4218 aligned word store.
4219 */
4220 IRExpr* data = st->Ist.Store.data;
4221 IRExpr* addr = st->Ist.Store.addr;
4222 IRType d_ty = typeOfIRExpr(pce->bb->tyenv, data);
4223 IRExpr* addrv = schemeEw_Atom( pce, addr );
4224 if (pce->gWordTy == Ity_I32) {
4225 /* ------ 32 bit host/guest (cough, cough) ------ */
4226 switch (d_ty) {
4227 /* Integer word case */
4228 case Ity_I32: {
4229 IRExpr* datav = schemeEw_Atom( pce, data );
4230 gen_dirty_v_WWWW( pce,
4231 &check_store4_P, "check_store4_P",
4232 addr, addrv, data, datav );
4233 break;
4234 }
4235 /* Integer subword cases */
4236 case Ity_I16:
4237 gen_dirty_v_WWW( pce,
4238 &check_store2, "check_store2",
4239 addr, addrv,
4240 uwiden_to_host_word( pce, data ));
4241 break;
4242 case Ity_I8:
4243 gen_dirty_v_WWW( pce,
4244 &check_store1, "check_store1",
4245 addr, addrv,
4246 uwiden_to_host_word( pce, data ));
4247 break;
4248 /* 64-bit float. Pass store data in 2 32-bit pieces. */
4249 case Ity_F64: {
4250 IRAtom* d64 = assignNew( 'I', pce, Ity_I64,
4251 unop(Iop_ReinterpF64asI64, data) );
4252 IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4253 unop(Iop_64to32, d64) );
4254 IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4255 unop(Iop_64HIto32, d64) );
4256 gen_dirty_v_WWWW( pce,
4257 &check_store8_ms4B_ls4B,
4258 "check_store8_ms4B_ls4B",
4259 addr, addrv, dHi32, dLo32 );
4260 break;
4261 }
4262 /* 32-bit float. We can just use _store4, but need
4263 to futz with the argument type. */
4264 case Ity_F32: {
4265 IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4266 unop(Iop_ReinterpF32asI32,
4267 data ) );
4268 gen_dirty_v_WWW( pce,
4269 &check_store4,
4270 "check_store4",
4271 addr, addrv, i32 );
4272 break;
4273 }
4274 /* 64-bit int. Pass store data in 2 32-bit pieces. */
4275 case Ity_I64: {
4276 IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4277 unop(Iop_64to32, data) );
4278 IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4279 unop(Iop_64HIto32, data) );
4280 gen_dirty_v_WWWW( pce,
4281 &check_store8_ms4B_ls4B,
4282 "check_store8_ms4B_ls4B",
4283 addr, addrv, dHi32, dLo32 );
4284 break;
4285 }
4286
4287 /* 128-bit vector. Pass store data in 4 32-bit pieces.
4288 This is all very ugly and inefficient, but it is
4289 hard to better without considerably complicating the
4290 store-handling schemes. */
4291 case Ity_V128: {
4292 IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4293 unop(Iop_V128HIto64, data) );
4294 IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4295 unop(Iop_V128to64, data) );
4296 IRAtom* w3 = assignNew( 'I', pce, Ity_I32,
4297 unop(Iop_64HIto32, dHi64) );
4298 IRAtom* w2 = assignNew( 'I', pce, Ity_I32,
4299 unop(Iop_64to32, dHi64) );
4300 IRAtom* w1 = assignNew( 'I', pce, Ity_I32,
4301 unop(Iop_64HIto32, dLo64) );
4302 IRAtom* w0 = assignNew( 'I', pce, Ity_I32,
4303 unop(Iop_64to32, dLo64) );
4304 gen_dirty_v_6W( pce,
4305 &check_store16_ms4B_4B_4B_ls4B,
4306 "check_store16_ms4B_4B_4B_ls4B",
4307 addr, addrv, w3, w2, w1, w0 );
4308 break;
4309 }
4310
4311
4312 default:
4313 ppIRType(d_ty); tl_assert(0);
4314 }
4315 } else {
4316 /* ------ 64 bit host/guest (cough, cough) ------ */
4317 switch (d_ty) {
4318 /* Integer word case */
4319 case Ity_I64: {
4320 IRExpr* datav = schemeEw_Atom( pce, data );
4321 gen_dirty_v_WWWW( pce,
4322 &check_store8_P, "check_store8_P",
4323 addr, addrv, data, datav );
4324 break;
4325 }
4326 /* Integer subword cases */
4327 case Ity_I32:
4328 gen_dirty_v_WWW( pce,
4329 &check_store4, "check_store4",
4330 addr, addrv,
4331 uwiden_to_host_word( pce, data ));
4332 break;
4333 case Ity_I16:
4334 gen_dirty_v_WWW( pce,
4335 &check_store2, "check_store2",
4336 addr, addrv,
4337 uwiden_to_host_word( pce, data ));
4338 break;
4339 case Ity_I8:
4340 gen_dirty_v_WWW( pce,
4341 &check_store1, "check_store1",
4342 addr, addrv,
4343 uwiden_to_host_word( pce, data ));
4344 break;
4345 /* 128-bit vector. Pass store data in 2 64-bit pieces. */
4346 case Ity_V128: {
4347 IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4348 unop(Iop_V128HIto64, data) );
4349 IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4350 unop(Iop_V128to64, data) );
4351 gen_dirty_v_WWWW( pce,
4352 &check_store16_ms8B_ls8B,
4353 "check_store16_ms8B_ls8B",
4354 addr, addrv, dHi64, dLo64 );
4355 break;
4356 }
4357 /* 64-bit float. */
4358 case Ity_F64: {
4359 IRAtom* dI = assignNew( 'I', pce, Ity_I64,
4360 unop(Iop_ReinterpF64asI64,
4361 data ) );
4362 gen_dirty_v_WWW( pce,
4363 &check_store8_all8B,
4364 "check_store8_all8B",
4365 addr, addrv, dI );
4366 break;
4367 }
4368 /* 32-bit float. We can just use _store4, but need
4369 to futz with the argument type. */
4370 case Ity_F32: {
4371 IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4372 unop(Iop_ReinterpF32asI32,
4373 data ) );
4374 IRAtom* i64 = assignNew( 'I', pce, Ity_I64,
4375 unop(Iop_32Uto64,
4376 i32 ) );
4377 gen_dirty_v_WWW( pce,
4378 &check_store4,
4379 "check_store4",
4380 addr, addrv, i64 );
4381 break;
4382 }
4383 default:
4384 ppIRType(d_ty); tl_assert(0);
4385 }
4386 }
4387 /* And don't copy the original, since the helper does the
4388 store. Ick. */
4389 break;
4390 } /* case Ist_Store */
4391
4392 case Ist_WrTmp: {
4393 /* This is the only place we have to deal with the full
4394 IRExpr range. In all other places where an IRExpr could
4395 appear, we in fact only get an atom (Iex_RdTmp or
4396 Iex_Const). */
4397 IRExpr* e = st->Ist.WrTmp.data;
4398 IRType e_ty = typeOfIRExpr( pce->bb->tyenv, e );
4399 Bool isWord = e_ty == pce->gWordTy;
4400 IRTemp dst = st->Ist.WrTmp.tmp;
4401 IRTemp dstv = isWord ? newShadowTmp( pce, dst )
4402 : IRTemp_INVALID;
4403
4404 switch (e->tag) {
4405
4406 case Iex_Const: {
4407 stmt( 'C', pce, st );
4408 if (isWord)
4409 assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) );
4410 break;
4411 }
4412
4413 case Iex_CCall: {
4414 stmt( 'C', pce, st );
4415 if (isWord)
4416 assign( 'I', pce, dstv,
4417 mkexpr( gen_call_nonptr_or_unknown_w(
4418 pce, mkexpr(dst))));
4419 break;
4420 }
4421
4422 case Iex_Mux0X: {
4423 /* Just steer the shadow values in the same way as the
4424 originals. */
4425 stmt( 'C', pce, st );
4426 if (isWord)
4427 assign( 'I', pce, dstv,
4428 IRExpr_Mux0X(
4429 e->Iex.Mux0X.cond,
4430 schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ),
4431 schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) ));
4432 break;
4433 }
4434
4435 case Iex_RdTmp: {
4436 stmt( 'C', pce, st );
4437 if (isWord)
4438 assign( 'I', pce, dstv, schemeEw_Atom( pce, e ));
4439 break;
4440 }
4441
4442 case Iex_Load: {
4443 IRExpr* addr = e->Iex.Load.addr;
4444 HChar* h_nm = NULL;
4445 void* h_fn = NULL;
4446 IRExpr* addrv = NULL;
4447 if (pce->gWordTy == Ity_I32) {
4448 /* 32 bit host/guest (cough, cough) */
4449 switch (e_ty) {
4450 /* Ity_I32: helper returns shadow value. */
4451 case Ity_I32: h_fn = &check_load4_P;
4452 h_nm = "check_load4_P"; break;
4453 /* all others: helper does not return a shadow
4454 value. */
4455 case Ity_V128: h_fn = &check_load16;
4456 h_nm = "check_load16"; break;
4457 case Ity_I64:
4458 case Ity_F64: h_fn = &check_load8;
4459 h_nm = "check_load8"; break;
4460 case Ity_F32: h_fn = &check_load4;
4461 h_nm = "check_load4"; break;
4462 case Ity_I16: h_fn = &check_load2;
4463 h_nm = "check_load2"; break;
4464 case Ity_I8: h_fn = &check_load1;
4465 h_nm = "check_load1"; break;
4466 default: ppIRType(e_ty); tl_assert(0);
4467 }
4468 addrv = schemeEw_Atom( pce, addr );
4469 if (e_ty == Ity_I32) {
4470 assign( 'I', pce, dstv,
4471 mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4472 addr, addrv )) );
4473 } else {
4474 gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4475 }
4476 } else {
4477 /* 64 bit host/guest (cough, cough) */
4478 switch (e_ty) {
4479 /* Ity_I64: helper returns shadow value. */
4480 case Ity_I64: h_fn = &check_load8_P;
4481 h_nm = "check_load8_P"; break;
4482 /* all others: helper does not return a shadow
4483 value. */
4484 case Ity_V128: h_fn = &check_load16;
4485 h_nm = "check_load16"; break;
4486 case Ity_F64: h_fn = &check_load8;
4487 h_nm = "check_load8"; break;
4488 case Ity_F32:
4489 case Ity_I32: h_fn = &check_load4;
4490 h_nm = "check_load4"; break;
4491 case Ity_I16: h_fn = &check_load2;
4492 h_nm = "check_load2"; break;
4493 case Ity_I8: h_fn = &check_load1;
4494 h_nm = "check_load1"; break;
4495 default: ppIRType(e_ty); tl_assert(0);
4496 }
4497 addrv = schemeEw_Atom( pce, addr );
4498 if (e_ty == Ity_I64) {
4499 assign( 'I', pce, dstv,
4500 mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4501 addr, addrv )) );
4502 } else {
4503 gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4504 }
4505 }
4506 /* copy the original -- must happen after the helper call */
4507 stmt( 'C', pce, st );
4508 break;
4509 }
4510
4511 case Iex_GetI: {
4512 IRRegArray* descr = e->Iex.GetI.descr;
4513 stmt( 'C', pce, st );
4514 tl_assert(descr && descr->elemTy);
4515 if (is_integer_guest_reg_array(descr)) {
4516 /* if this fails, is_integer_guest_reg_array is
4517 returning bogus results */
4518 tl_assert(isWord);
4519 assign(
4520 'I', pce, dstv,
4521 IRExpr_GetI(
4522 mkIRRegArray(descr->base + pce->guest_state_sizeB,
4523 descr->elemTy, descr->nElems),
4524 e->Iex.GetI.ix,
4525 e->Iex.GetI.bias
4526 )
4527 );
4528 }
4529 break;
4530 }
4531
4532 case Iex_Get: {
4533 stmt( 'C', pce, st );
4534 if (isWord) {
4535 /* guest-word-typed tmp assignment, so it will have a
4536 shadow tmp, and we must make an assignment to
4537 that */
4538 if (is_integer_guest_reg(e->Iex.Get.offset,
4539 sizeofIRType(e->Iex.Get.ty))) {
4540 assign( 'I', pce, dstv,
4541 IRExpr_Get( e->Iex.Get.offset
4542 + pce->guest_state_sizeB,
4543 e->Iex.Get.ty) );
4544 } else {
4545 if (pce->hWordTy == Ity_I32) {
4546 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4547 } else {
4548 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4549 }
4550 }
4551 } else {
4552 /* tmp isn't guest-word-typed, so isn't shadowed, so
4553 generate no instrumentation */
4554 }
4555 break;
4556 }
4557
4558 case Iex_Unop: {
4559 stmt( 'C', pce, st );
4560 tl_assert(isIRAtom(e->Iex.Unop.arg));
4561 if (isWord)
4562 instrument_arithop( pce, dst, dstv, e->Iex.Unop.op,
4563 e->Iex.Unop.arg,
4564 NULL, NULL, NULL );
4565 break;
4566 }
4567
4568 case Iex_Binop: {
4569 stmt( 'C', pce, st );
4570 tl_assert(isIRAtom(e->Iex.Binop.arg1));
4571 tl_assert(isIRAtom(e->Iex.Binop.arg2));
4572 if (isWord)
4573 instrument_arithop( pce, dst, dstv, e->Iex.Binop.op,
4574 e->Iex.Binop.arg1, e->Iex.Binop.arg2,
4575 NULL, NULL );
4576 break;
4577 }
4578
4579 case Iex_Triop: {
4580 stmt( 'C', pce, st );
4581 tl_assert(isIRAtom(e->Iex.Triop.arg1));
4582 tl_assert(isIRAtom(e->Iex.Triop.arg2));
4583 tl_assert(isIRAtom(e->Iex.Triop.arg3));
4584 if (isWord)
4585 instrument_arithop( pce, dst, dstv, e->Iex.Triop.op,
4586 e->Iex.Triop.arg1, e->Iex.Triop.arg2,
4587 e->Iex.Triop.arg3, NULL );
4588 break;
4589 }
4590
4591 case Iex_Qop: {
4592 stmt( 'C', pce, st );
4593 tl_assert(isIRAtom(e->Iex.Qop.arg1));
4594 tl_assert(isIRAtom(e->Iex.Qop.arg2));
4595 tl_assert(isIRAtom(e->Iex.Qop.arg3));
4596 tl_assert(isIRAtom(e->Iex.Qop.arg4));
4597 if (isWord)
4598 instrument_arithop( pce, dst, dstv, e->Iex.Qop.op,
4599 e->Iex.Qop.arg1, e->Iex.Qop.arg2,
4600 e->Iex.Qop.arg3, e->Iex.Qop.arg4 );
4601 break;
4602 }
4603
4604 default:
4605 goto unhandled;
4606 } /* switch (e->tag) */
4607
4608 break;
4609
4610 } /* case Ist_WrTmp */
4611
4612 default:
4613 unhandled:
4614 ppIRStmt(st);
4615 tl_assert(0);
4616 }
4617}
4618
4619
4620IRSB* h_instrument ( VgCallbackClosure* closure,
4621 IRSB* sbIn,
4622 VexGuestLayout* layout,
4623 VexGuestExtents* vge,
4624 IRType gWordTy, IRType hWordTy )
4625{
4626 Bool verboze = 0||False;
4627 Int i /*, j*/;
4628 PCEnv pce;
4629 struct _SGEnv* sgenv;
4630
4631 if (gWordTy != hWordTy) {
4632 /* We don't currently support this case. */
4633 VG_(tool_panic)("host/guest word size mismatch");
4634 }
4635
4636 /* Check we're not completely nuts */
4637 tl_assert(sizeof(UWord) == sizeof(void*));
4638 tl_assert(sizeof(Word) == sizeof(void*));
4639 tl_assert(sizeof(Addr) == sizeof(void*));
4640 tl_assert(sizeof(ULong) == 8);
4641 tl_assert(sizeof(Long) == 8);
4642 tl_assert(sizeof(Addr64) == 8);
4643 tl_assert(sizeof(UInt) == 4);
4644 tl_assert(sizeof(Int) == 4);
4645
4646 /* Set up the running environment. Only .bb is modified as we go
4647 along. */
4648 pce.bb = deepCopyIRSBExceptStmts(sbIn);
4649 pce.trace = verboze;
4650 pce.n_originalTmps = sbIn->tyenv->types_used;
4651 pce.hWordTy = hWordTy;
4652 pce.gWordTy = gWordTy;
4653 pce.guest_state_sizeB = layout->total_sizeB;
4654 pce.tmpMap = LibVEX_Alloc(pce.n_originalTmps * sizeof(IRTemp));
4655 for (i = 0; i < pce.n_originalTmps; i++)
4656 pce.tmpMap[i] = IRTemp_INVALID;
4657
4658 /* Also set up for the sg_ instrumenter. See comments
4659 at the top of this instrumentation section for details. */
4660 sgenv = sg_instrument_init();
4661
4662 /* Stay sane. These two should agree! */
4663 tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE);
4664
4665 /* Copy verbatim any IR preamble preceding the first IMark */
4666
4667 i = 0;
4668 while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
4669 IRStmt* st = sbIn->stmts[i];
4670 tl_assert(st);
4671 tl_assert(isFlatIRStmt(st));
4672 stmt( 'C', &pce, sbIn->stmts[i] );
4673 i++;
4674 }
4675
4676 /* Nasty problem. IR optimisation of the pre-instrumented IR may
4677 cause the IR following the preamble to contain references to IR
4678 temporaries defined in the preamble. Because the preamble isn't
4679 instrumented, these temporaries don't have any shadows.
4680 Nevertheless uses of them following the preamble will cause
4681 memcheck to generate references to their shadows. End effect is
4682 to cause IR sanity check failures, due to references to
4683 non-existent shadows. This is only evident for the complex
4684 preambles used for function wrapping on TOC-afflicted platforms
4685 (ppc64-linux, ppc32-aix5, ppc64-aix5).
4686
4687 The following loop therefore scans the preamble looking for
4688 assignments to temporaries. For each one found it creates an
4689 assignment to the corresponding shadow temp, marking it as
4690 'defined'. This is the same resulting IR as if the main
4691 instrumentation loop before had been applied to the statement
4692 'tmp = CONSTANT'.
4693 */
4694#if 0
4695 // FIXME: this isn't exactly right; only needs to generate shadows
4696 // for guest-word-typed temps
4697 for (j = 0; j < i; j++) {
4698 if (sbIn->stmts[j]->tag == Ist_WrTmp) {
4699 /* findShadowTmpV checks its arg is an original tmp;
4700 no need to assert that here. */
4701 IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp;
4702 IRTemp tmp_s = findShadowTmp(&pce, tmp_o);
4703 IRType ty_s = typeOfIRTemp(sbIn->tyenv, tmp_s);
4704 assign( 'V', &pce, tmp_s, definedOfType( ty_s ) );
4705 if (0) {
4706 VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
4707 ppIRType( ty_s );
4708 VG_(printf)("\n");
4709 }
4710 }
4711 }
4712#endif
4713
4714 /* Iterate over the remaining stmts to generate instrumentation. */
4715
4716 tl_assert(sbIn->stmts_used > 0);
4717 tl_assert(i >= 0);
4718 tl_assert(i < sbIn->stmts_used);
4719 tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
4720
4721 for (/*use current i*/; i < sbIn->stmts_used; i++) {
4722 /* generate sg_ instrumentation for this stmt */
4723 sg_instrument_IRStmt( sgenv, pce.bb, sbIn->stmts[i],
4724 layout, gWordTy, hWordTy );
4725 /* generate h_ instrumentation for this stmt */
4726 schemeS( &pce, sbIn->stmts[i] );
4727 }
4728
4729 /* generate sg_ instrumentation for the final jump */
4730 sg_instrument_final_jump( sgenv, pce.bb, sbIn->next, sbIn->jumpkind,
4731 layout, gWordTy, hWordTy );
4732
4733 /* and finalise .. */
4734 sg_instrument_fini( sgenv );
4735
4736 return pce.bb;
4737}
4738
4739
4740/*--------------------------------------------------------------------*/
4741/*--- Initialisation ---*/
4742/*--------------------------------------------------------------------*/
4743
4744void h_pre_clo_init ( void )
4745{
4746 // Other initialisation
4747 init_shadow_memory();
4748 init_lossage();
4749}
4750
4751void h_post_clo_init ( void )
4752{
4753}
4754
4755/*--------------------------------------------------------------------*/
4756/*--- Finalisation ---*/
4757/*--------------------------------------------------------------------*/
4758
4759void h_fini ( Int exitcode )
4760{
4761 if (VG_(clo_verbosity) >= 2) {
4762 VG_(message)(Vg_DebugMsg,
4763 " h_: %'10llu client allocs, %'10llu client frees",
4764 stats__client_mallocs, stats__client_frees);
4765 VG_(message)(Vg_DebugMsg,
4766 " h_: %'10llu Segs allocd, %'10llu Segs recycled",
4767 stats__segs_allocd, stats__segs_recycled);
sewardj024598e2008-09-18 14:43:05 +00004768 }
4769
sewardj4815eb52008-10-20 23:33:49 +00004770#if 0
sewardj024598e2008-09-18 14:43:05 +00004771 if (h_clo_lossage_check) {
4772 VG_(message)(Vg_UserMsg, "");
4773 VG_(message)(Vg_UserMsg, "%12lld total memory references",
4774 stats__tot_mem_refs);
4775 VG_(message)(Vg_UserMsg, "%12lld of which are in a known segment",
4776 stats__refs_in_a_seg);
4777 VG_(message)(Vg_UserMsg, "%12lld of which are 'lost' w.r.t the seg",
4778 stats__refs_lost_seg);
4779 VG_(message)(Vg_UserMsg, "");
4780 show_lossage();
4781 VG_(message)(Vg_UserMsg, "");
4782 } else {
4783 tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
4784 }
sewardj4815eb52008-10-20 23:33:49 +00004785#endif
sewardj024598e2008-09-18 14:43:05 +00004786}
4787
4788
4789/*--------------------------------------------------------------------*/
4790/*--- end h_main.c ---*/
4791/*--------------------------------------------------------------------*/