blob: 50f4154cd5147a613a39b8b673783f2b3b9ffa7e [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
njn9f207462009-03-10 22:02:09 +000014 Copyright (C) 2003-2009 Nicholas Nethercote
sewardj024598e2008-09-18 14:43:05 +000015 njn@valgrind.org
16
17 Valgrind-3.X port:
18
njn9f207462009-03-10 22:02:09 +000019 Copyright (C) 2008-2009 OpenWorks Ltd
sewardj024598e2008-09-18 14:43:05 +000020 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);
sewardjad039492009-01-29 08:44:49 +0000857 if (vMax == (UWord)&maxSeg) {
sewardj95208452008-10-18 19:55:31 +0000858 /* 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
njn8b140de2009-02-17 04:31:18 +00001002SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p )
1003{
1004 Seg* seg = find_Seg_by_addr( (Addr)p );
1005
1006 // There may be slop, but pretend there isn't because only the asked-for
1007 // area will have been shadowed properly.
1008 return ( seg ? seg->szB : 0 );
1009}
1010
sewardj024598e2008-09-18 14:43:05 +00001011
1012/*------------------------------------------------------------*/
1013/*--- Memory events ---*/
1014/*------------------------------------------------------------*/
1015
1016static inline
1017void set_mem ( Addr a, SizeT len, Seg* seg )
1018{
1019 Addr end;
1020
1021 if (0 == len)
1022 return;
1023
1024 if (len > 100 * 1000 * 1000)
1025 VG_(message)(Vg_UserMsg,
1026 "Warning: set address range state: large range %lu", len);
1027
1028 a = VG_ROUNDDN(a, sizeof(UWord));
1029 end = VG_ROUNDUP(a + len, sizeof(UWord));
1030 for ( ; a < end; a += sizeof(UWord))
1031 set_mem_vseg(a, seg);
1032}
1033
1034static void set_mem_unknown( Addr a, SizeT len )
1035{
1036 set_mem( a, len, UNKNOWN );
1037}
1038
1039//zz static void set_mem_nonptr( Addr a, UInt len )
1040//zz {
1041//zz set_mem( a, len, NONPTR );
1042//zz }
1043
1044void h_new_mem_startup( Addr a, SizeT len,
1045 Bool rr, Bool ww, Bool xx, ULong di_handle )
1046{
1047 if (0) VG_(printf)("new_mem_startup(%#lx,%lu)\n", a, len);
1048 set_mem_unknown( a, len );
1049 //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1050}
1051
1052//zz // XXX: Currently not doing anything with brk() -- new segments, or not?
1053//zz // Proper way to do it would be to grow/shrink a single, special brk segment.
1054//zz //
1055//zz // brk is difficult: it defines a single segment, of changeable size.
1056//zz // It starts off with size zero, at the address given by brk(0). There are
1057//zz // no pointers within the program to it. Any subsequent calls by the
1058//zz // program to brk() (possibly growing or shrinking it) return pointers to
1059//zz // the *end* of the segment (nb: this is the kernel brk(), which is
1060//zz // different to the libc brk()).
1061//zz //
1062//zz // If fixing this, don't forget to update the brk case in SK_(post_syscall).
1063//zz //
1064//zz // Nb: not sure if the return value is the last byte addressible, or one
1065//zz // past the end of the segment.
1066//zz //
1067//zz static void new_mem_brk( Addr a, UInt len )
1068//zz {
1069//zz set_mem_unknown(a, len);
1070//zz //VG_(skin_panic)("can't handle new_mem_brk");
1071//zz }
1072
1073// Not quite right: if you mmap a segment into a specified place, it could
1074// be legitimate to do certain arithmetic with the pointer that it wouldn't
1075// otherwise. Hopefully this is rare, though.
1076void h_new_mem_mmap( Addr a, SizeT len,
1077 Bool rr, Bool ww, Bool xx, ULong di_handle )
1078{
1079 if (0) VG_(printf)("new_mem_mmap(%#lx,%lu)\n", a, len);
1080//zz #if 0
1081//zz Seg seg = NULL;
1082//zz
1083//zz // Check for overlapping segments
1084//zz #if 0
1085//zz is_overlapping_seg___a = a; // 'free' variable
1086//zz is_overlapping_seg___len = len; // 'free' variable
1087//zz seg = (Seg)VG_(HT_first_match) ( mlist, is_overlapping_seg );
1088//zz is_overlapping_seg___a = 0; // paranoia, reset
1089//zz is_overlapping_seg___len = 0; // paranoia, reset
1090//zz #endif
1091//zz
1092//zz // XXX: do this check properly with ISLists
1093//zz
1094//zz if ( ISList__findI( seglist, a, &seg )) {
1095//zz sk_assert(SegMmap == seg->status || SegMmapFree == seg->status);
1096//zz if (SegMmap == seg->status)
1097//zz
1098//zz }
1099//zz
1100//zz if (NULL != seg) {
1101//zz // Right, we found an overlap
1102//zz if (VG_(clo_verbosity) > 1)
1103//zz VG_(message)(Vg_UserMsg, "mmap overlap: old: %#lx, %d; new: %#lx, %d",
1104//zz seg->left, Seg__size(seg), a, len);
1105//zz if (seg->left <= a && a <= seg->right) {
1106//zz // New one truncates end of the old one. Nb: we don't adjust its
1107//zz // size, because the first segment's pointer can be (and for
1108//zz // Konqueror, is) legitimately used to access parts of the second
1109//zz // segment. At least, I assume Konqueror is doing something legal.
1110//zz // so that a size mismatch upon munmap isn't a problem.
1111//zz // seg->size = a - seg->data;
1112//zz // seg->is_truncated_map = True;
1113//zz // if (VG_(clo_verbosity) > 1)
1114//zz // VG_(message)(Vg_UserMsg, "old seg truncated to length %d",
1115//zz // seg->size);
1116//zz } else {
1117//zz VG_(skin_panic)("Can't handle this mmap() overlap case");
1118//zz }
1119//zz }
1120 set_mem_unknown( a, len );
1121 //add_new_segment( VG_(get_running_tid)(), a, len, SegMmap );
1122//zz #endif
1123}
1124
1125static void copy_mem( Addr from, Addr to, SizeT len )
1126{
1127 Addr fromend = from + len;
1128
1129 // Must be aligned due to malloc always returning aligned objects.
1130 tl_assert(VG_IS_8_ALIGNED(from) && VG_IS_8_ALIGNED(to));
1131
1132 // Must only be called with positive len.
1133 if (0 == len)
1134 return;
1135
1136 for ( ; from < fromend; from += sizeof(UWord), to += sizeof(UWord))
1137 set_mem_vseg( to, get_mem_vseg(from) );
1138}
1139
1140//zz // Similar to SK_(realloc)()
1141//zz static void copy_mem_remap( Addr from, Addr to, UInt len )
1142//zz {
1143//zz VG_(skin_panic)("argh: copy_mem_remap");
1144//zz }
1145//zz
1146//zz static void die_mem_brk( Addr a, UInt len )
1147//zz {
1148//zz set_mem_unknown(a, len);
1149//zz // VG_(skin_panic)("can't handle die_mem_brk()");
1150//zz }
1151
1152void h_die_mem_munmap( Addr a, SizeT len )
1153{
1154// handle_free_munmap( (void*)a, len );
1155}
1156
1157// Don't need to check all addresses within the block; in the absence of
1158// discontiguous segments, the segments for the first and last bytes should
1159// be the same. Can't easily check the pointer segment matches the block
1160// segment, unfortunately, but the first/last check should catch most
1161// errors.
1162static void pre_mem_access2 ( CorePart part, ThreadId tid, Char* str,
1163 Addr s/*tart*/, Addr e/*nd*/ )
1164{
1165 Seg *seglo, *seghi;
sewardj024598e2008-09-18 14:43:05 +00001166
1167 // Don't check code being translated -- very slow, and not much point
1168 if (Vg_CoreTranslate == part) return;
1169
1170 // Don't check the signal case -- only happens in core, no need to check
1171 if (Vg_CoreSignal == part) return;
1172
1173 // Only expect syscalls after this point
1174 if (part != Vg_CoreSysCall) {
1175 VG_(printf)("part = %d\n", part);
1176 VG_(tool_panic)("unknown corepart in pre_mem_access2");
1177 }
1178
1179 // Check first and last bytes match
sewardj95208452008-10-18 19:55:31 +00001180 seglo = get_Seg_containing_addr( s );
1181 seghi = get_Seg_containing_addr( e );
sewardj024598e2008-09-18 14:43:05 +00001182 tl_assert( BOTTOM != seglo && NONPTR != seglo );
1183 tl_assert( BOTTOM != seghi && NONPTR != seghi );
1184
njn4c245e52009-03-15 23:25:38 +00001185 /* record an error if start and end are in different, but known segments */
sewardj024598e2008-09-18 14:43:05 +00001186 if (is_known_segment(seglo) && is_known_segment(seghi)
1187 && seglo != seghi) {
1188 h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
1189 }
1190 else
1191 /* record an error if start is in a known segment but end isn't */
1192 if (is_known_segment(seglo) && !is_known_segment(seghi)) {
1193 h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
1194 }
1195 else
1196 /* record an error if end is in a known segment but start isn't */
1197 if (!is_known_segment(seglo) && is_known_segment(seghi)) {
1198 h_record_sysparam_error(tid, part, str, s, e, UNKNOWN, seghi);
1199 }
1200}
1201
1202void h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
1203 Addr base, SizeT size )
1204{
1205 pre_mem_access2( part, tid, s, base, base + size - 1 );
1206}
1207
1208void h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
1209 Char* s, Addr lo )
1210{
1211 Addr hi = lo;
1212
1213 // Nb: the '\0' must be included in the lo...hi range
1214 while ('\0' != *(Char*)hi) hi++;
1215 pre_mem_access2( part, tid, s, lo, hi );
1216}
1217
1218//zz static void post_mem_write(Addr a, UInt len)
1219//zz {
1220//zz set_mem_unknown(a, len);
1221//zz }
1222
1223
1224/*------------------------------------------------------------*/
1225/*--- Register event handlers ---*/
1226/*------------------------------------------------------------*/
1227
1228//zz static void post_regs_write_init ( void )
1229//zz {
1230//zz UInt i;
1231//zz for (i = R_EAX; i <= R_EDI; i++)
1232//zz VG_(set_shadow_archreg)( i, (UInt)UNKNOWN );
1233//zz
1234//zz // Don't bother about eflags
1235//zz }
1236
1237// BEGIN move this uglyness to pc_machine.c
1238
1239static inline Bool host_is_big_endian ( void ) {
1240 UInt x = 0x11223344;
1241 return 0x1122 == *(UShort*)(&x);
1242}
1243static inline Bool host_is_little_endian ( void ) {
1244 UInt x = 0x11223344;
1245 return 0x3344 == *(UShort*)(&x);
1246}
1247
1248#define N_INTREGINFO_OFFSETS 4
1249
1250/* Holds the result of a query to 'get_IntRegInfo'. Valid values for
1251 n_offsets are:
1252
1253 -1: means the queried guest state slice exactly matches
1254 one integer register
1255
1256 0: means the queried guest state slice does not overlap any
1257 integer registers
1258
1259 1 .. N_INTREGINFO_OFFSETS: means the queried guest state offset
1260 overlaps n_offsets different integer registers, and their base
1261 offsets are placed in the offsets array.
1262*/
1263typedef
1264 struct {
1265 Int offsets[N_INTREGINFO_OFFSETS];
1266 Int n_offsets;
1267 }
1268 IntRegInfo;
1269
1270
1271#if defined(VGA_x86)
1272# include "libvex_guest_x86.h"
1273# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestX86State)
1274#endif
1275
1276#if defined(VGA_amd64)
1277# include "libvex_guest_amd64.h"
1278# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestAMD64State)
1279# define PC_OFF_FS_ZERO offsetof(VexGuestAMD64State,guest_FS_ZERO)
1280# define PC_SZB_FS_ZERO sizeof( ((VexGuestAMD64State*)0)->guest_FS_ZERO)
1281#endif
1282
1283#if defined(VGA_ppc32)
1284# include "libvex_guest_ppc32.h"
1285# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC32State)
1286#endif
1287
1288#if defined(VGA_ppc64)
1289# include "libvex_guest_ppc64.h"
1290# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
1291#endif
1292
1293
1294/* See description on definition of type IntRegInfo. */
1295static void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
1296{
1297 /* --------------------- x86 --------------------- */
1298
1299# if defined(VGA_x86)
1300
1301# define GOF(_fieldname) \
1302 (offsetof(VexGuestX86State,guest_##_fieldname))
1303
1304 Int o = offset;
1305 Int sz = szB;
1306 Bool is4 = sz == 4;
1307 Bool is21 = sz == 2 || sz == 1;
1308
1309 tl_assert(sz > 0);
1310 tl_assert(host_is_little_endian());
1311
1312 /* Set default state to "does not intersect any int register". */
1313 VG_(memset)( iii, 0, sizeof(*iii) );
1314
1315 /* Exact accesses to integer registers */
1316 if (o == GOF(EAX) && is4) goto exactly1;
1317 if (o == GOF(ECX) && is4) goto exactly1;
1318 if (o == GOF(EDX) && is4) goto exactly1;
1319 if (o == GOF(EBX) && is4) goto exactly1;
1320 if (o == GOF(ESP) && is4) goto exactly1;
1321 if (o == GOF(EBP) && is4) goto exactly1;
1322 if (o == GOF(ESI) && is4) goto exactly1;
1323 if (o == GOF(EDI) && is4) goto exactly1;
1324 if (o == GOF(EIP) && is4) goto none;
sewardj5685ade2009-03-30 02:34:29 +00001325 if (o == GOF(IP_AT_SYSCALL) && is4) goto none;
sewardj024598e2008-09-18 14:43:05 +00001326 if (o == GOF(CC_OP) && is4) goto none;
1327 if (o == GOF(CC_DEP1) && is4) goto none;
1328 if (o == GOF(CC_DEP2) && is4) goto none;
1329 if (o == GOF(CC_NDEP) && is4) goto none;
1330 if (o == GOF(DFLAG) && is4) goto none;
1331 if (o == GOF(IDFLAG) && is4) goto none;
1332 if (o == GOF(ACFLAG) && is4) goto none;
1333
1334 /* Partial accesses to integer registers */
1335 if (o == GOF(EAX) && is21) { o -= 0; goto contains_o; }
1336 if (o == GOF(EAX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1337 if (o == GOF(ECX) && is21) { o -= 0; goto contains_o; }
1338 if (o == GOF(ECX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1339 if (o == GOF(EBX) && is21) { o -= 0; goto contains_o; }
sewardjdb440982008-10-11 10:18:16 +00001340 if (o == GOF(EBX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
sewardj024598e2008-09-18 14:43:05 +00001341 if (o == GOF(EDX) && is21) { o -= 0; goto contains_o; }
1342 if (o == GOF(EDX)+1 && is21) { o -= 1; o -= 0; goto contains_o; }
1343 if (o == GOF(ESI) && is21) { o -= 0; goto contains_o; }
1344 if (o == GOF(EDI) && is21) { o -= 0; goto contains_o; }
1345
1346 /* Segment related guff */
1347 if (o == GOF(GS) && sz == 2) goto none;
1348 if (o == GOF(LDT) && is4) goto none;
1349 if (o == GOF(GDT) && is4) goto none;
1350
1351 /* FP admin related */
1352 if (o == GOF(SSEROUND) && is4) goto none;
1353 if (o == GOF(FPROUND) && is4) goto none;
1354 if (o == GOF(EMWARN) && is4) goto none;
1355 if (o == GOF(FTOP) && is4) goto none;
1356 if (o == GOF(FPTAG) && sz == 8) goto none;
1357 if (o == GOF(FC3210) && is4) goto none;
1358
1359 /* xmm registers, including arbitrary sub-parts */
1360 if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1361 if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1362 if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1363 if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1364 if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1365 if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1366 if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1367 if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1368
1369 /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1370 to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1371 if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1372
1373 /* the entire mmx/x87 register bank in one big piece */
1374 if (o == GOF(FPREG) && sz == 64) goto none;
1375
1376 VG_(printf)("get_IntRegInfo(x86):failing on (%d,%d)\n", o, sz);
1377 tl_assert(0);
1378# undef GOF
1379
1380 /* -------------------- amd64 -------------------- */
1381
1382# elif defined(VGA_amd64)
1383
1384# define GOF(_fieldname) \
1385 (offsetof(VexGuestAMD64State,guest_##_fieldname))
1386
1387 Int o = offset;
1388 Int sz = szB;
1389 Bool is421 = sz == 4 || sz == 2 || sz == 1;
1390 Bool is8 = sz == 8;
1391
1392 tl_assert(sz > 0);
1393 tl_assert(host_is_little_endian());
1394
1395 /* Set default state to "does not intersect any int register". */
1396 VG_(memset)( iii, 0, sizeof(*iii) );
1397
1398 /* Exact accesses to integer registers */
1399 if (o == GOF(RAX) && is8) goto exactly1;
1400 if (o == GOF(RCX) && is8) goto exactly1;
1401 if (o == GOF(RDX) && is8) goto exactly1;
1402 if (o == GOF(RBX) && is8) goto exactly1;
1403 if (o == GOF(RSP) && is8) goto exactly1;
1404 if (o == GOF(RBP) && is8) goto exactly1;
1405 if (o == GOF(RSI) && is8) goto exactly1;
1406 if (o == GOF(RDI) && is8) goto exactly1;
1407 if (o == GOF(R8) && is8) goto exactly1;
1408 if (o == GOF(R9) && is8) goto exactly1;
1409 if (o == GOF(R10) && is8) goto exactly1;
1410 if (o == GOF(R11) && is8) goto exactly1;
1411 if (o == GOF(R12) && is8) goto exactly1;
1412 if (o == GOF(R13) && is8) goto exactly1;
1413 if (o == GOF(R14) && is8) goto exactly1;
1414 if (o == GOF(R15) && is8) goto exactly1;
1415 if (o == GOF(RIP) && is8) goto exactly1;
sewardj5685ade2009-03-30 02:34:29 +00001416 if (o == GOF(IP_AT_SYSCALL) && is8) goto none;
sewardj024598e2008-09-18 14:43:05 +00001417 if (o == GOF(CC_OP) && is8) goto none;
1418 if (o == GOF(CC_DEP1) && is8) goto none;
1419 if (o == GOF(CC_DEP2) && is8) goto none;
1420 if (o == GOF(CC_NDEP) && is8) goto none;
1421 if (o == GOF(DFLAG) && is8) goto none;
1422 if (o == GOF(IDFLAG) && is8) goto none;
1423
1424 /* Partial accesses to integer registers */
1425 if (o == GOF(RAX) && is421) { o -= 0; goto contains_o; }
1426 if (o == GOF(RAX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1427 if (o == GOF(RCX) && is421) { o -= 0; goto contains_o; }
1428 if (o == GOF(RCX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1429 if (o == GOF(RDX) && is421) { o -= 0; goto contains_o; }
1430 if (o == GOF(RDX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1431 if (o == GOF(RBX) && is421) { o -= 0; goto contains_o; }
1432 if (o == GOF(RBX)+1 && is421) { o -= 1; o -= 0; goto contains_o; }
1433 if (o == GOF(RBP) && is421) { o -= 0; goto contains_o; }
1434 if (o == GOF(RSI) && is421) { o -= 0; goto contains_o; }
1435 if (o == GOF(RDI) && is421) { o -= 0; goto contains_o; }
1436 if (o == GOF(R8) && is421) { o -= 0; goto contains_o; }
1437 if (o == GOF(R9) && is421) { o -= 0; goto contains_o; }
1438 if (o == GOF(R10) && is421) { o -= 0; goto contains_o; }
1439 if (o == GOF(R11) && is421) { o -= 0; goto contains_o; }
1440 if (o == GOF(R12) && is421) { o -= 0; goto contains_o; }
1441 if (o == GOF(R13) && is421) { o -= 0; goto contains_o; }
1442 if (o == GOF(R14) && is421) { o -= 0; goto contains_o; }
1443 if (o == GOF(R15) && is421) { o -= 0; goto contains_o; }
1444
1445 /* Segment related guff */
1446 if (o == GOF(FS_ZERO) && is8) goto exactly1;
1447
1448 /* FP admin related */
1449 if (o == GOF(SSEROUND) && is8) goto none;
1450 if (o == GOF(FPROUND) && is8) goto none;
1451 if (o == GOF(EMWARN) && sz == 4) goto none;
1452 if (o == GOF(FTOP) && sz == 4) goto none;
1453 if (o == GOF(FPTAG) && is8) goto none;
1454 if (o == GOF(FC3210) && is8) goto none;
1455
1456 /* xmm registers, including arbitrary sub-parts */
1457 if (o >= GOF(XMM0) && o+sz <= GOF(XMM0)+16) goto none;
1458 if (o >= GOF(XMM1) && o+sz <= GOF(XMM1)+16) goto none;
1459 if (o >= GOF(XMM2) && o+sz <= GOF(XMM2)+16) goto none;
1460 if (o >= GOF(XMM3) && o+sz <= GOF(XMM3)+16) goto none;
1461 if (o >= GOF(XMM4) && o+sz <= GOF(XMM4)+16) goto none;
1462 if (o >= GOF(XMM5) && o+sz <= GOF(XMM5)+16) goto none;
1463 if (o >= GOF(XMM6) && o+sz <= GOF(XMM6)+16) goto none;
1464 if (o >= GOF(XMM7) && o+sz <= GOF(XMM7)+16) goto none;
1465 if (o >= GOF(XMM8) && o+sz <= GOF(XMM8)+16) goto none;
1466 if (o >= GOF(XMM9) && o+sz <= GOF(XMM9)+16) goto none;
1467 if (o >= GOF(XMM10) && o+sz <= GOF(XMM10)+16) goto none;
1468 if (o >= GOF(XMM11) && o+sz <= GOF(XMM11)+16) goto none;
1469 if (o >= GOF(XMM12) && o+sz <= GOF(XMM12)+16) goto none;
1470 if (o >= GOF(XMM13) && o+sz <= GOF(XMM13)+16) goto none;
1471 if (o >= GOF(XMM14) && o+sz <= GOF(XMM14)+16) goto none;
1472 if (o >= GOF(XMM15) && o+sz <= GOF(XMM15)+16) goto none;
1473
1474 /* mmx/x87 registers (a bit of a kludge, since 'o' is not checked
1475 to be exactly equal to one of FPREG[0] .. FPREG[7]) */
1476 if (o >= GOF(FPREG[0]) && o < GOF(FPREG[7])+8 && sz == 8) goto none;
1477
1478 VG_(printf)("get_IntRegInfo(amd64):failing on (%d,%d)\n", o, sz);
1479 tl_assert(0);
1480# undef GOF
1481
1482 /* -------------------- ppc32 -------------------- */
1483
1484# elif defined(VGA_ppc32)
1485
1486# define GOF(_fieldname) \
1487 (offsetof(VexGuestPPC32State,guest_##_fieldname))
1488
1489 Int o = offset;
1490 Int sz = szB;
1491 Bool is4 = sz == 4;
1492 Bool is8 = sz == 8;
1493
1494 tl_assert(sz > 0);
1495 tl_assert(host_is_big_endian());
1496
1497 /* Set default state to "does not intersect any int register". */
1498 VG_(memset)( iii, 0, sizeof(*iii) );
1499
1500 /* Exact accesses to integer registers */
1501 if (o == GOF(GPR0) && is4) goto exactly1;
1502 if (o == GOF(GPR1) && is4) goto exactly1;
1503 if (o == GOF(GPR2) && is4) goto exactly1;
1504 if (o == GOF(GPR3) && is4) goto exactly1;
1505 if (o == GOF(GPR4) && is4) goto exactly1;
1506 if (o == GOF(GPR5) && is4) goto exactly1;
1507 if (o == GOF(GPR6) && is4) goto exactly1;
1508 if (o == GOF(GPR7) && is4) goto exactly1;
1509 if (o == GOF(GPR8) && is4) goto exactly1;
1510 if (o == GOF(GPR9) && is4) goto exactly1;
1511 if (o == GOF(GPR10) && is4) goto exactly1;
1512 if (o == GOF(GPR11) && is4) goto exactly1;
1513 if (o == GOF(GPR12) && is4) goto exactly1;
1514 if (o == GOF(GPR13) && is4) goto exactly1;
1515 if (o == GOF(GPR14) && is4) goto exactly1;
1516 if (o == GOF(GPR15) && is4) goto exactly1;
1517 if (o == GOF(GPR16) && is4) goto exactly1;
1518 if (o == GOF(GPR17) && is4) goto exactly1;
1519 if (o == GOF(GPR18) && is4) goto exactly1;
1520 if (o == GOF(GPR19) && is4) goto exactly1;
1521 if (o == GOF(GPR20) && is4) goto exactly1;
1522 if (o == GOF(GPR21) && is4) goto exactly1;
1523 if (o == GOF(GPR22) && is4) goto exactly1;
1524 if (o == GOF(GPR23) && is4) goto exactly1;
1525 if (o == GOF(GPR24) && is4) goto exactly1;
1526 if (o == GOF(GPR25) && is4) goto exactly1;
1527 if (o == GOF(GPR26) && is4) goto exactly1;
1528 if (o == GOF(GPR27) && is4) goto exactly1;
1529 if (o == GOF(GPR28) && is4) goto exactly1;
1530 if (o == GOF(GPR29) && is4) goto exactly1;
1531 if (o == GOF(GPR30) && is4) goto exactly1;
1532 if (o == GOF(GPR31) && is4) goto exactly1;
1533
1534 /* Misc integer reg and condition code accesses */
1535 if (o == GOF(LR) && is4) goto exactly1;
1536 if (o == GOF(CTR) && is4) goto exactly1;
1537 if (o == GOF(CIA) && is4) goto none;
sewardj90fc9d72009-03-20 00:28:50 +00001538 if (o == GOF(IP_AT_SYSCALL) && is4) goto none;
sewardj024598e2008-09-18 14:43:05 +00001539 if (o == GOF(RESVN) && is4) goto none;
1540 if (o == GOF(TISTART) && is4) goto none;
1541 if (o == GOF(TILEN) && is4) goto none;
1542 if (o == GOF(REDIR_SP) && is4) goto none;
1543
1544 if (sz == 1) {
1545 if (o == GOF(XER_SO)) goto none;
1546 if (o == GOF(XER_OV)) goto none;
1547 if (o == GOF(XER_CA)) goto none;
1548 if (o == GOF(XER_BC)) goto none;
1549 if (o == GOF(CR0_321)) goto none;
1550 if (o == GOF(CR0_0)) goto none;
1551 if (o == GOF(CR1_321)) goto none;
1552 if (o == GOF(CR1_0)) goto none;
1553 if (o == GOF(CR2_321)) goto none;
1554 if (o == GOF(CR2_0)) goto none;
1555 if (o == GOF(CR3_321)) goto none;
1556 if (o == GOF(CR3_0)) goto none;
1557 if (o == GOF(CR4_321)) goto none;
1558 if (o == GOF(CR4_0)) goto none;
1559 if (o == GOF(CR5_321)) goto none;
1560 if (o == GOF(CR5_0)) goto none;
1561 if (o == GOF(CR6_321)) goto none;
1562 if (o == GOF(CR6_0)) goto none;
1563 if (o == GOF(CR7_321)) goto none;
1564 if (o == GOF(CR7_0)) goto none;
1565 }
1566
1567 /* Exact accesses to FP registers */
1568 if (o == GOF(FPR0) && is8) goto none;
1569 if (o == GOF(FPR1) && is8) goto none;
1570 if (o == GOF(FPR2) && is8) goto none;
1571 if (o == GOF(FPR3) && is8) goto none;
1572 if (o == GOF(FPR4) && is8) goto none;
1573 if (o == GOF(FPR5) && is8) goto none;
1574 if (o == GOF(FPR6) && is8) goto none;
1575 if (o == GOF(FPR7) && is8) goto none;
1576 if (o == GOF(FPR8) && is8) goto none;
1577 if (o == GOF(FPR9) && is8) goto none;
1578 if (o == GOF(FPR10) && is8) goto none;
1579 if (o == GOF(FPR11) && is8) goto none;
1580 if (o == GOF(FPR12) && is8) goto none;
1581 if (o == GOF(FPR13) && is8) goto none;
1582 if (o == GOF(FPR14) && is8) goto none;
1583 if (o == GOF(FPR15) && is8) goto none;
1584 if (o == GOF(FPR16) && is8) goto none;
1585 if (o == GOF(FPR17) && is8) goto none;
1586 if (o == GOF(FPR18) && is8) goto none;
1587 if (o == GOF(FPR19) && is8) goto none;
1588 if (o == GOF(FPR20) && is8) goto none;
1589 if (o == GOF(FPR21) && is8) goto none;
1590 if (o == GOF(FPR22) && is8) goto none;
1591 if (o == GOF(FPR23) && is8) goto none;
1592 if (o == GOF(FPR24) && is8) goto none;
1593 if (o == GOF(FPR25) && is8) goto none;
1594 if (o == GOF(FPR26) && is8) goto none;
1595 if (o == GOF(FPR27) && is8) goto none;
1596 if (o == GOF(FPR28) && is8) goto none;
1597 if (o == GOF(FPR29) && is8) goto none;
1598 if (o == GOF(FPR30) && is8) goto none;
1599 if (o == GOF(FPR31) && is8) goto none;
1600
1601 /* FP admin related */
1602 if (o == GOF(FPROUND) && is4) goto none;
1603 if (o == GOF(EMWARN) && is4) goto none;
1604
1605 /* Altivec registers */
1606 if (o == GOF(VR0) && sz == 16) goto none;
1607 if (o == GOF(VR1) && sz == 16) goto none;
1608 if (o == GOF(VR2) && sz == 16) goto none;
1609 if (o == GOF(VR3) && sz == 16) goto none;
1610 if (o == GOF(VR4) && sz == 16) goto none;
1611 if (o == GOF(VR5) && sz == 16) goto none;
1612 if (o == GOF(VR6) && sz == 16) goto none;
1613 if (o == GOF(VR7) && sz == 16) goto none;
1614 if (o == GOF(VR8) && sz == 16) goto none;
1615 if (o == GOF(VR9) && sz == 16) goto none;
1616 if (o == GOF(VR10) && sz == 16) goto none;
1617 if (o == GOF(VR11) && sz == 16) goto none;
1618 if (o == GOF(VR12) && sz == 16) goto none;
1619 if (o == GOF(VR13) && sz == 16) goto none;
1620 if (o == GOF(VR14) && sz == 16) goto none;
1621 if (o == GOF(VR15) && sz == 16) goto none;
1622 if (o == GOF(VR16) && sz == 16) goto none;
1623 if (o == GOF(VR17) && sz == 16) goto none;
1624 if (o == GOF(VR18) && sz == 16) goto none;
1625 if (o == GOF(VR19) && sz == 16) goto none;
1626 if (o == GOF(VR20) && sz == 16) goto none;
1627 if (o == GOF(VR21) && sz == 16) goto none;
1628 if (o == GOF(VR22) && sz == 16) goto none;
1629 if (o == GOF(VR23) && sz == 16) goto none;
1630 if (o == GOF(VR24) && sz == 16) goto none;
1631 if (o == GOF(VR25) && sz == 16) goto none;
1632 if (o == GOF(VR26) && sz == 16) goto none;
1633 if (o == GOF(VR27) && sz == 16) goto none;
1634 if (o == GOF(VR28) && sz == 16) goto none;
1635 if (o == GOF(VR29) && sz == 16) goto none;
1636 if (o == GOF(VR30) && sz == 16) goto none;
1637 if (o == GOF(VR31) && sz == 16) goto none;
1638
sewardjaae82082008-10-21 23:10:18 +00001639 /* Altivec admin related */
1640 if (o == GOF(VRSAVE) && is4) goto none;
1641
sewardj024598e2008-09-18 14:43:05 +00001642 VG_(printf)("get_IntRegInfo(ppc32):failing on (%d,%d)\n", o, sz);
1643 tl_assert(0);
1644# undef GOF
1645
1646 /* -------------------- ppc64 -------------------- */
1647
1648# elif defined(VGA_ppc64)
1649
1650# define GOF(_fieldname) \
1651 (offsetof(VexGuestPPC64State,guest_##_fieldname))
1652
1653 Int o = offset;
1654 Int sz = szB;
1655 Bool is4 = sz == 4;
1656 Bool is8 = sz == 8;
1657
1658 tl_assert(sz > 0);
1659 tl_assert(host_is_big_endian());
1660
1661 /* Set default state to "does not intersect any int register". */
1662 VG_(memset)( iii, 0, sizeof(*iii) );
1663
1664 /* Exact accesses to integer registers */
1665 if (o == GOF(GPR0) && is8) goto exactly1;
1666 if (o == GOF(GPR1) && is8) goto exactly1;
1667 if (o == GOF(GPR2) && is8) goto exactly1;
1668 if (o == GOF(GPR3) && is8) goto exactly1;
1669 if (o == GOF(GPR4) && is8) goto exactly1;
1670 if (o == GOF(GPR5) && is8) goto exactly1;
1671 if (o == GOF(GPR6) && is8) goto exactly1;
1672 if (o == GOF(GPR7) && is8) goto exactly1;
1673 if (o == GOF(GPR8) && is8) goto exactly1;
1674 if (o == GOF(GPR9) && is8) goto exactly1;
1675 if (o == GOF(GPR10) && is8) goto exactly1;
1676 if (o == GOF(GPR11) && is8) goto exactly1;
1677 if (o == GOF(GPR12) && is8) goto exactly1;
1678 if (o == GOF(GPR13) && is8) goto exactly1;
1679 if (o == GOF(GPR14) && is8) goto exactly1;
1680 if (o == GOF(GPR15) && is8) goto exactly1;
1681 if (o == GOF(GPR16) && is8) goto exactly1;
1682 if (o == GOF(GPR17) && is8) goto exactly1;
1683 if (o == GOF(GPR18) && is8) goto exactly1;
1684 if (o == GOF(GPR19) && is8) goto exactly1;
1685 if (o == GOF(GPR20) && is8) goto exactly1;
1686 if (o == GOF(GPR21) && is8) goto exactly1;
1687 if (o == GOF(GPR22) && is8) goto exactly1;
1688 if (o == GOF(GPR23) && is8) goto exactly1;
1689 if (o == GOF(GPR24) && is8) goto exactly1;
1690 if (o == GOF(GPR25) && is8) goto exactly1;
1691 if (o == GOF(GPR26) && is8) goto exactly1;
1692 if (o == GOF(GPR27) && is8) goto exactly1;
1693 if (o == GOF(GPR28) && is8) goto exactly1;
1694 if (o == GOF(GPR29) && is8) goto exactly1;
1695 if (o == GOF(GPR30) && is8) goto exactly1;
1696 if (o == GOF(GPR31) && is8) goto exactly1;
1697
1698 /* Misc integer reg and condition code accesses */
1699 if (o == GOF(LR) && is8) goto exactly1;
1700 if (o == GOF(CTR) && is8) goto exactly1;
1701 if (o == GOF(CIA) && is8) goto none;
sewardj90fc9d72009-03-20 00:28:50 +00001702 if (o == GOF(IP_AT_SYSCALL) && is8) goto none;
sewardj024598e2008-09-18 14:43:05 +00001703 if (o == GOF(RESVN) && is8) goto none;
1704 if (o == GOF(TISTART) && is8) goto none;
1705 if (o == GOF(TILEN) && is8) goto none;
1706 if (o == GOF(REDIR_SP) && is8) goto none;
1707
1708 if (sz == 1) {
1709 if (o == GOF(XER_SO)) goto none;
1710 if (o == GOF(XER_OV)) goto none;
1711 if (o == GOF(XER_CA)) goto none;
1712 if (o == GOF(XER_BC)) goto none;
1713 if (o == GOF(CR0_321)) goto none;
1714 if (o == GOF(CR0_0)) goto none;
1715 if (o == GOF(CR1_321)) goto none;
1716 if (o == GOF(CR1_0)) goto none;
1717 if (o == GOF(CR2_321)) goto none;
1718 if (o == GOF(CR2_0)) goto none;
1719 if (o == GOF(CR3_321)) goto none;
1720 if (o == GOF(CR3_0)) goto none;
1721 if (o == GOF(CR4_321)) goto none;
1722 if (o == GOF(CR4_0)) goto none;
1723 if (o == GOF(CR5_321)) goto none;
1724 if (o == GOF(CR5_0)) goto none;
1725 if (o == GOF(CR6_321)) goto none;
1726 if (o == GOF(CR6_0)) goto none;
1727 if (o == GOF(CR7_321)) goto none;
1728 if (o == GOF(CR7_0)) goto none;
1729 }
1730
1731 /* Exact accesses to FP registers */
1732 if (o == GOF(FPR0) && is8) goto none;
1733 if (o == GOF(FPR1) && is8) goto none;
1734 if (o == GOF(FPR2) && is8) goto none;
1735 if (o == GOF(FPR3) && is8) goto none;
1736 if (o == GOF(FPR4) && is8) goto none;
1737 if (o == GOF(FPR5) && is8) goto none;
1738 if (o == GOF(FPR6) && is8) goto none;
1739 if (o == GOF(FPR7) && is8) goto none;
1740 if (o == GOF(FPR8) && is8) goto none;
1741 if (o == GOF(FPR9) && is8) goto none;
1742 if (o == GOF(FPR10) && is8) goto none;
1743 if (o == GOF(FPR11) && is8) goto none;
1744 if (o == GOF(FPR12) && is8) goto none;
1745 if (o == GOF(FPR13) && is8) goto none;
1746 if (o == GOF(FPR14) && is8) goto none;
1747 if (o == GOF(FPR15) && is8) goto none;
1748 if (o == GOF(FPR16) && is8) goto none;
1749 if (o == GOF(FPR17) && is8) goto none;
1750 if (o == GOF(FPR18) && is8) goto none;
1751 if (o == GOF(FPR19) && is8) goto none;
1752 if (o == GOF(FPR20) && is8) goto none;
1753 if (o == GOF(FPR21) && is8) goto none;
1754 if (o == GOF(FPR22) && is8) goto none;
1755 if (o == GOF(FPR23) && is8) goto none;
1756 if (o == GOF(FPR24) && is8) goto none;
1757 if (o == GOF(FPR25) && is8) goto none;
1758 if (o == GOF(FPR26) && is8) goto none;
1759 if (o == GOF(FPR27) && is8) goto none;
1760 if (o == GOF(FPR28) && is8) goto none;
1761 if (o == GOF(FPR29) && is8) goto none;
1762 if (o == GOF(FPR30) && is8) goto none;
1763 if (o == GOF(FPR31) && is8) goto none;
1764
1765 /* FP admin related */
1766 if (o == GOF(FPROUND) && is4) goto none;
1767 if (o == GOF(EMWARN) && is4) goto none;
1768
1769 /* Altivec registers */
1770 if (o == GOF(VR0) && sz == 16) goto none;
1771 if (o == GOF(VR1) && sz == 16) goto none;
1772 if (o == GOF(VR2) && sz == 16) goto none;
1773 if (o == GOF(VR3) && sz == 16) goto none;
1774 if (o == GOF(VR4) && sz == 16) goto none;
1775 if (o == GOF(VR5) && sz == 16) goto none;
1776 if (o == GOF(VR6) && sz == 16) goto none;
1777 if (o == GOF(VR7) && sz == 16) goto none;
1778 if (o == GOF(VR8) && sz == 16) goto none;
1779 if (o == GOF(VR9) && sz == 16) goto none;
1780 if (o == GOF(VR10) && sz == 16) goto none;
1781 if (o == GOF(VR11) && sz == 16) goto none;
1782 if (o == GOF(VR12) && sz == 16) goto none;
1783 if (o == GOF(VR13) && sz == 16) goto none;
1784 if (o == GOF(VR14) && sz == 16) goto none;
1785 if (o == GOF(VR15) && sz == 16) goto none;
1786 if (o == GOF(VR16) && sz == 16) goto none;
1787 if (o == GOF(VR17) && sz == 16) goto none;
1788 if (o == GOF(VR18) && sz == 16) goto none;
1789 if (o == GOF(VR19) && sz == 16) goto none;
1790 if (o == GOF(VR20) && sz == 16) goto none;
1791 if (o == GOF(VR21) && sz == 16) goto none;
1792 if (o == GOF(VR22) && sz == 16) goto none;
1793 if (o == GOF(VR23) && sz == 16) goto none;
1794 if (o == GOF(VR24) && sz == 16) goto none;
1795 if (o == GOF(VR25) && sz == 16) goto none;
1796 if (o == GOF(VR26) && sz == 16) goto none;
1797 if (o == GOF(VR27) && sz == 16) goto none;
1798 if (o == GOF(VR28) && sz == 16) goto none;
1799 if (o == GOF(VR29) && sz == 16) goto none;
1800 if (o == GOF(VR30) && sz == 16) goto none;
1801 if (o == GOF(VR31) && sz == 16) goto none;
1802
sewardjaae82082008-10-21 23:10:18 +00001803 /* Altivec admin related */
1804 if (o == GOF(VRSAVE) && is4) goto none;
1805
sewardj024598e2008-09-18 14:43:05 +00001806 VG_(printf)("get_IntRegInfo(ppc64):failing on (%d,%d)\n", o, sz);
1807 tl_assert(0);
1808# undef GOF
1809
1810
1811# else
1812# error "FIXME: not implemented for this architecture"
1813# endif
1814
1815 exactly1:
1816 iii->n_offsets = -1;
1817 return;
1818 none:
1819 iii->n_offsets = 0;
1820 return;
1821 contains_o:
1822 tl_assert(o >= 0 && 0 == (o % sizeof(UWord)));
1823 iii->n_offsets = 1;
1824 iii->offsets[0] = o;
1825 return;
1826}
1827
1828
1829/* Does 'arr' describe an indexed guest state section containing host
1830 words, that we want to shadow? */
1831
1832static Bool is_integer_guest_reg_array ( IRRegArray* arr )
1833{
1834 /* --------------------- x86 --------------------- */
1835# if defined(VGA_x86)
1836 /* The x87 tag array. */
1837 if (arr->base == offsetof(VexGuestX86State,guest_FPTAG[0])
1838 && arr->elemTy == Ity_I8 && arr->nElems == 8)
1839 return False;
1840 /* The x87 register array. */
1841 if (arr->base == offsetof(VexGuestX86State,guest_FPREG[0])
1842 && arr->elemTy == Ity_F64 && arr->nElems == 8)
1843 return False;
1844
1845 VG_(printf)("is_integer_guest_reg_array(x86): unhandled: ");
1846 ppIRRegArray(arr);
1847 VG_(printf)("\n");
1848 tl_assert(0);
1849
1850 /* -------------------- amd64 -------------------- */
1851# elif defined(VGA_amd64)
1852 /* The x87 tag array. */
1853 if (arr->base == offsetof(VexGuestAMD64State,guest_FPTAG[0])
1854 && arr->elemTy == Ity_I8 && arr->nElems == 8)
1855 return False;
1856 /* The x87 register array. */
1857 if (arr->base == offsetof(VexGuestAMD64State,guest_FPREG[0])
1858 && arr->elemTy == Ity_F64 && arr->nElems == 8)
1859 return False;
1860
1861 VG_(printf)("is_integer_guest_reg_array(amd64): unhandled: ");
1862 ppIRRegArray(arr);
1863 VG_(printf)("\n");
1864 tl_assert(0);
1865
1866 /* -------------------- ppc32 -------------------- */
1867# elif defined(VGA_ppc32)
1868 /* The redir stack. */
1869 if (arr->base == offsetof(VexGuestPPC32State,guest_REDIR_STACK[0])
1870 && arr->elemTy == Ity_I32
1871 && arr->nElems == VEX_GUEST_PPC32_REDIR_STACK_SIZE)
1872 return True;
1873
1874 VG_(printf)("is_integer_guest_reg_array(ppc32): unhandled: ");
1875 ppIRRegArray(arr);
1876 VG_(printf)("\n");
1877 tl_assert(0);
1878
1879 /* -------------------- ppc64 -------------------- */
1880# elif defined(VGA_ppc64)
1881 /* The redir stack. */
1882 if (arr->base == offsetof(VexGuestPPC64State,guest_REDIR_STACK[0])
1883 && arr->elemTy == Ity_I64
1884 && arr->nElems == VEX_GUEST_PPC64_REDIR_STACK_SIZE)
1885 return True;
1886
1887 VG_(printf)("is_integer_guest_reg_array(ppc64): unhandled: ");
1888 ppIRRegArray(arr);
1889 VG_(printf)("\n");
1890 tl_assert(0);
1891
1892# else
1893# error "FIXME: not implemented for this architecture"
1894# endif
1895}
1896
1897
1898// END move this uglyness to pc_machine.c
1899
1900/* returns True iff given slice exactly matches an int reg. Merely
1901 a convenience wrapper around get_IntRegInfo. */
1902static Bool is_integer_guest_reg ( Int offset, Int szB )
1903{
1904 IntRegInfo iii;
1905 get_IntRegInfo( &iii, offset, szB );
1906 tl_assert(iii.n_offsets >= -1 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
1907 return iii.n_offsets == -1;
1908}
1909
1910/* these assume guest and host have the same endianness and
1911 word size (probably). */
1912static UWord get_guest_intreg ( ThreadId tid, Int shadowNo,
njnc4431bf2009-01-15 21:29:24 +00001913 PtrdiffT offset, SizeT size )
sewardj024598e2008-09-18 14:43:05 +00001914{
1915 UChar tmp[ 2 + sizeof(UWord) ];
1916 tl_assert(size == sizeof(UWord));
1917 tl_assert(0 == (offset % sizeof(UWord)));
1918 VG_(memset)(tmp, 0, sizeof(tmp));
1919 tmp[0] = 0x31;
1920 tmp[ sizeof(tmp)-1 ] = 0x27;
1921 VG_(get_shadow_regs_area)(tid, &tmp[1], shadowNo, offset, size);
1922 tl_assert(tmp[0] == 0x31);
1923 tl_assert(tmp[ sizeof(tmp)-1 ] == 0x27);
1924 return * ((UWord*) &tmp[1] ); /* MISALIGNED LOAD */
1925}
1926static void put_guest_intreg ( ThreadId tid, Int shadowNo,
njnc4431bf2009-01-15 21:29:24 +00001927 PtrdiffT offset, SizeT size, UWord w )
sewardj024598e2008-09-18 14:43:05 +00001928{
1929 tl_assert(size == sizeof(UWord));
1930 tl_assert(0 == (offset % sizeof(UWord)));
1931 VG_(set_shadow_regs_area)(tid, shadowNo, offset, size,
1932 (const UChar*)&w);
1933}
1934
1935/* Initialise the integer shadow registers to UNKNOWN. This is a bit
1936 of a nasty kludge, but it does mean we don't need to know which
1937 registers we really need to initialise -- simply assume that all
1938 integer registers will be naturally aligned w.r.t. the start of the
1939 guest state, and fill in all possible entries. */
1940static void init_shadow_registers ( ThreadId tid )
1941{
1942 Int i, wordSzB = sizeof(UWord);
1943 for (i = 0; i < MC_SIZEOF_GUEST_STATE-wordSzB; i += wordSzB) {
1944 put_guest_intreg( tid, 1, i, wordSzB, (UWord)UNKNOWN );
1945 }
1946}
1947
njnc4431bf2009-01-15 21:29:24 +00001948static void post_reg_write_nonptr ( ThreadId tid, PtrdiffT offset, SizeT size )
sewardj024598e2008-09-18 14:43:05 +00001949{
1950 // syscall_return: Default is non-pointer. If it really is a pointer
1951 // (eg. for mmap()), SK_(post_syscall) sets it again afterwards.
1952 //
1953 // clientreq_return: All the global client requests return non-pointers
1954 // (except possibly CLIENT_CALL[0123], but they're handled by
1955 // post_reg_write_clientcall, not here).
1956 //
1957 if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1958 put_guest_intreg( tid, 1, offset, size, (UWord)NONPTR );
1959 } else {
1960 tl_assert(0);
1961 }
1962 // VG_(set_thread_shadow_archreg)( tid, reg, (UInt)NONPTR );
1963}
1964
1965static void post_reg_write_nonptr_or_unknown ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00001966 PtrdiffT offset, SizeT size )
sewardj024598e2008-09-18 14:43:05 +00001967{
1968 // deliver_signal: called from two places; one sets the reg to zero, the
1969 // other sets the stack pointer.
1970 //
1971 if (is_integer_guest_reg( (Int)offset, (Int)size )) {
1972 put_guest_intreg(
1973 tid, 1/*shadowno*/, offset, size,
1974 (UWord)nonptr_or_unknown(
1975 get_guest_intreg( tid, 0/*shadowno*/,
1976 offset, size )));
1977 } else {
1978 tl_assert(0);
1979 }
1980}
1981
1982void h_post_reg_write_demux ( CorePart part, ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00001983 PtrdiffT guest_state_offset, SizeT size)
sewardj024598e2008-09-18 14:43:05 +00001984{
1985 if (0)
1986 VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
1987 (Int)tid, (Int)part,
1988 guest_state_offset, size);
1989 switch (part) {
1990 case Vg_CoreStartup:
1991 /* This is a bit of a kludge since for any Vg_CoreStartup
1992 event we overwrite the entire shadow register set. But
1993 that's ok - we're only called once with
1994 part==Vg_CoreStartup event, and in that case the supplied
1995 offset & size cover the entire guest state anyway. */
1996 init_shadow_registers(tid);
1997 break;
1998 case Vg_CoreSysCall:
1999 if (0) VG_(printf)("ZZZZZZZ p_r_w -> NONPTR\n");
2000 post_reg_write_nonptr( tid, guest_state_offset, size );
2001 break;
2002 case Vg_CoreClientReq:
2003 post_reg_write_nonptr( tid, guest_state_offset, size );
2004 break;
2005 case Vg_CoreSignal:
2006 post_reg_write_nonptr_or_unknown( tid, guest_state_offset, size );
2007 break;
2008 default:
2009 tl_assert(0);
2010 }
2011}
2012
njnc4431bf2009-01-15 21:29:24 +00002013void h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
sewardj024598e2008-09-18 14:43:05 +00002014 SizeT size, Addr f )
2015{
2016 UWord p;
2017
2018 // Having to do this is a bit nasty...
2019 if (f == (Addr)h_replace_malloc
2020 || f == (Addr)h_replace___builtin_new
2021 || f == (Addr)h_replace___builtin_vec_new
2022 || f == (Addr)h_replace_calloc
2023 || f == (Addr)h_replace_memalign
2024 || f == (Addr)h_replace_realloc)
2025 {
2026 // We remembered the last added segment; make sure it's the right one.
2027 /* What's going on: at this point, the scheduler has just called
2028 'f' -- one of our malloc replacement functions -- and it has
2029 returned. The return value has been written to the guest
2030 state of thread 'tid', offset 'guest_state_offset' length
2031 'size'. We need to look at that return value and set the
2032 shadow return value accordingly. The shadow return value
2033 required is handed to us "under the counter" through the
2034 global variable 'last_seg_added'. This is all very ugly, not
2035 to mention, non-thread-safe should V ever become
2036 multithreaded. */
2037 /* assert the place where the return value is is a legit int reg */
2038 tl_assert(is_integer_guest_reg(guest_state_offset, size));
2039 /* Now we need to look at the returned value, to see whether the
2040 malloc succeeded or not. */
2041 p = get_guest_intreg(tid, 0/*non-shadow*/, guest_state_offset, size);
2042 if ((UWord)NULL == p) {
2043 // if alloc failed, eg. realloc on bogus pointer
2044 put_guest_intreg(tid, 1/*first-shadow*/,
2045 guest_state_offset, size, (UWord)NONPTR );
2046 } else {
2047 // alloc didn't fail. Check we have the correct segment.
2048 tl_assert(p == last_seg_added->addr);
2049 put_guest_intreg(tid, 1/*first-shadow*/,
2050 guest_state_offset, size, (UWord)last_seg_added );
2051 }
2052 }
2053 else if (f == (Addr)h_replace_free
2054 || f == (Addr)h_replace___builtin_delete
2055 || f == (Addr)h_replace___builtin_vec_delete
2056 // || f == (Addr)VG_(cli_block_size)
2057 || f == (Addr)VG_(message))
2058 {
2059 // Probably best to set the (non-existent!) return value to
2060 // non-pointer.
2061 tl_assert(is_integer_guest_reg(guest_state_offset, size));
2062 put_guest_intreg(tid, 1/*first-shadow*/,
2063 guest_state_offset, size, (UWord)NONPTR );
2064 }
2065 else {
2066 // Anything else, probably best to set return value to non-pointer.
2067 //VG_(set_thread_shadow_archreg)(tid, reg, (UInt)UNKNOWN);
2068 Char fbuf[100];
2069 VG_(printf)("f = %#lx\n", f);
2070 VG_(get_fnname)(f, fbuf, 100);
2071 VG_(printf)("name = %s\n", fbuf);
2072 VG_(tool_panic)("argh: clientcall");
2073 }
2074}
2075
2076
2077//zz /*--------------------------------------------------------------------*/
2078//zz /*--- Sanity checking ---*/
2079//zz /*--------------------------------------------------------------------*/
2080//zz
2081//zz /* Check that nobody has spuriously claimed that the first or last 16
2082//zz pages (64 KB) of address space have become accessible. Failure of
2083//zz the following do not per se indicate an internal consistency
2084//zz problem, but they are so likely to that we really want to know
2085//zz about it if so. */
2086//zz Bool pc_replace_cheap_sanity_check) ( void )
2087//zz {
2088//zz if (IS_DISTINGUISHED_SM(primary_map[0])
2089//zz /* kludge: kernel drops a page up at top of address range for
2090//zz magic "optimized syscalls", so we can no longer check the
2091//zz highest page */
2092//zz /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
2093//zz )
2094//zz return True;
2095//zz else
2096//zz return False;
2097//zz }
2098//zz
2099//zz Bool SK_(expensive_sanity_check) ( void )
2100//zz {
2101//zz Int i;
2102//zz
2103//zz /* Make sure nobody changed the distinguished secondary. */
2104//zz for (i = 0; i < SEC_MAP_WORDS; i++)
2105//zz if (distinguished_secondary_map.vseg[i] != UNKNOWN)
2106//zz return False;
2107//zz
2108//zz return True;
2109//zz }
2110
2111
2112/*--------------------------------------------------------------------*/
2113/*--- System calls ---*/
2114/*--------------------------------------------------------------------*/
2115
2116void h_pre_syscall ( ThreadId tid, UInt sysno )
2117{
2118 /* we don't do anything at the pre-syscall point */
2119}
2120
2121/* The post-syscall table is a table of pairs (number, flag).
2122
2123 'flag' is only ever zero or one. If it is zero, it indicates that
2124 default handling for that syscall is required -- namely that the
2125 syscall is deemed to return NONPTR. This is the case for the vast
2126 majority of syscalls. If it is one then some special
2127 syscall-specific handling is is required. No further details of it
2128 are stored in the table.
2129
2130 On Linux, 'number' is a __NR_xxx constant.
2131
2132 On AIX5, 'number' is an Int*, which points to the Int variable
2133 holding the currently assigned number for this syscall.
2134
2135 When querying the table, we compare the supplied syscall number
2136 with the 'number' field (directly on Linux, after dereferencing on
2137 AIX5), to find the relevant entry. This requires a linear search
2138 of the table. To stop the costs getting too high, the table is
2139 incrementally rearranged after each search, to move commonly
2140 requested items a bit closer to the front.
2141
2142 The table is built once, the first time it is used. After that we
2143 merely query it (and reorder the entries as a result). */
2144
2145static XArray* /* of UWordPair */ post_syscall_table = NULL;
2146
2147static void setup_post_syscall_table ( void )
2148{
2149 tl_assert(!post_syscall_table);
2150 post_syscall_table = VG_(newXA)( VG_(malloc), "pc.h_main.spst.1",
2151 VG_(free), sizeof(UWordPair) );
2152 tl_assert(post_syscall_table);
2153
2154 /* --------------- LINUX --------------- */
2155
2156# if defined(VGO_linux)
2157
2158# define ADD(_flag, _syscallname) \
2159 do { UWordPair p; p.uw1 = (_syscallname); p.uw2 = (_flag); \
2160 VG_(addToXA)( post_syscall_table, &p ); \
2161 } while (0)
2162
2163 /* These ones definitely don't return pointers. They're not
2164 particularly grammatical, either. */
2165
2166# if defined(__NR__llseek)
2167 ADD(0, __NR__llseek);
2168# endif
2169 ADD(0, __NR__sysctl);
2170# if defined(__NR__newselect)
2171 ADD(0, __NR__newselect);
2172# endif
2173# if defined(__NR_accept)
2174 ADD(0, __NR_accept);
2175# endif
2176 ADD(0, __NR_access);
tom332ffec2009-01-05 12:16:21 +00002177 ADD(0, __NR_alarm);
sewardj024598e2008-09-18 14:43:05 +00002178# if defined(__NR_bind)
2179 ADD(0, __NR_bind);
2180# endif
2181# if defined(__NR_chdir)
2182 ADD(0, __NR_chdir);
2183# endif
2184 ADD(0, __NR_chmod);
2185 ADD(0, __NR_chown);
sewardj41d5dea2009-01-24 10:52:32 +00002186# if defined(__NR_chown32)
2187 ADD(0, __NR_chown32);
2188# endif
sewardj024598e2008-09-18 14:43:05 +00002189 ADD(0, __NR_clock_getres);
2190 ADD(0, __NR_clock_gettime);
2191 ADD(0, __NR_clone);
2192 ADD(0, __NR_close);
2193# if defined(__NR_connect)
2194 ADD(0, __NR_connect);
2195# endif
tom332ffec2009-01-05 12:16:21 +00002196 ADD(0, __NR_creat);
sewardj024598e2008-09-18 14:43:05 +00002197 ADD(0, __NR_dup);
2198 ADD(0, __NR_dup2);
2199 ADD(0, __NR_execve); /* presumably we see this because the call failed? */
2200 ADD(0, __NR_exit); /* hmm, why are we still alive? */
2201 ADD(0, __NR_exit_group);
2202 ADD(0, __NR_fadvise64);
sewardj9f52ee42009-02-23 16:56:15 +00002203 ADD(0, __NR_fallocate);
sewardj024598e2008-09-18 14:43:05 +00002204 ADD(0, __NR_fchmod);
2205 ADD(0, __NR_fchown);
2206# if defined(__NR_fchown32)
2207 ADD(0, __NR_fchown32);
2208# endif
2209 ADD(0, __NR_fcntl);
2210# if defined(__NR_fcntl64)
2211 ADD(0, __NR_fcntl64);
2212# endif
2213 ADD(0, __NR_fdatasync);
sewardj33c57f22009-01-26 00:09:08 +00002214 ADD(0, __NR_flock);
sewardj024598e2008-09-18 14:43:05 +00002215 ADD(0, __NR_fstat);
2216# if defined(__NR_fstat64)
2217 ADD(0, __NR_fstat64);
2218# endif
2219 ADD(0, __NR_fstatfs);
2220 ADD(0, __NR_fsync);
2221 ADD(0, __NR_ftruncate);
2222# if defined(__NR_ftruncate64)
2223 ADD(0, __NR_ftruncate64);
2224# endif
2225 ADD(0, __NR_futex);
2226 ADD(0, __NR_getcwd);
2227 ADD(0, __NR_getdents); // something to do with teeth
2228 ADD(0, __NR_getdents64);
2229 ADD(0, __NR_getegid);
2230# if defined(__NR_getegid32)
2231 ADD(0, __NR_getegid32);
2232# endif
2233 ADD(0, __NR_geteuid);
2234# if defined(__NR_geteuid32)
2235 ADD(0, __NR_geteuid32);
2236# endif
2237 ADD(0, __NR_getgid);
2238# if defined(__NR_getgid32)
2239 ADD(0, __NR_getgid32);
2240# endif
sewardjad039492009-01-29 08:44:49 +00002241 ADD(0, __NR_getgroups);
sewardj024598e2008-09-18 14:43:05 +00002242 ADD(0, __NR_getitimer);
2243# if defined(__NR_getpeername)
2244 ADD(0, __NR_getpeername);
2245# endif
2246 ADD(0, __NR_getpid);
sewardj7d769112008-10-30 01:44:03 +00002247 ADD(0, __NR_getpgrp);
sewardj024598e2008-09-18 14:43:05 +00002248 ADD(0, __NR_getppid);
2249 ADD(0, __NR_getresgid);
2250 ADD(0, __NR_getresuid);
sewardj9f52ee42009-02-23 16:56:15 +00002251# if defined(__NR_getresuid32)
2252 ADD(0, __NR_getresuid32);
2253# endif
sewardj024598e2008-09-18 14:43:05 +00002254 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);
sewardjad039492009-01-29 08:44:49 +00002338 ADD(0, __NR_setfsgid);
2339 ADD(0, __NR_setfsuid);
2340 ADD(0, __NR_setgid);
sewardj024598e2008-09-18 14:43:05 +00002341 ADD(0, __NR_setitimer);
sewardj7d769112008-10-30 01:44:03 +00002342 ADD(0, __NR_setpgid);
sewardjad039492009-01-29 08:44:49 +00002343 ADD(0, __NR_setresgid);
sewardj024598e2008-09-18 14:43:05 +00002344 ADD(0, __NR_setrlimit);
2345 ADD(0, __NR_setsid);
2346# if defined(__NR_setsockopt)
2347 ADD(0, __NR_setsockopt);
2348# endif
sewardjad039492009-01-29 08:44:49 +00002349 ADD(0, __NR_setuid);
sewardj024598e2008-09-18 14:43:05 +00002350# if defined(__NR_shmctl)
2351 ADD(0, __NR_shmctl);
2352 ADD(0, __NR_shmdt);
2353# endif
2354# if defined(__NR_shutdown)
2355 ADD(0, __NR_shutdown);
2356# endif
sewardj41d5dea2009-01-24 10:52:32 +00002357 ADD(0, __NR_sigaltstack);
sewardj024598e2008-09-18 14:43:05 +00002358# if defined(__NR_socket)
2359 ADD(0, __NR_socket);
2360# endif
2361# if defined(__NR_socketcall)
2362 ADD(0, __NR_socketcall); /* the nasty x86-linux socket multiplexor */
2363# endif
sewardj23e8a292009-01-07 09:35:10 +00002364# if defined(__NR_socketpair)
2365 ADD(0, __NR_socketpair);
2366# endif
sewardj024598e2008-09-18 14:43:05 +00002367# if defined(__NR_statfs64)
2368 ADD(0, __NR_statfs64);
2369# endif
2370# if defined(__NR_sigreturn)
2371 ADD(0, __NR_sigreturn); /* not sure if we should see this or not */
2372# endif
2373# if defined(__NR_stat64)
2374 ADD(0, __NR_stat64);
2375# endif
2376 ADD(0, __NR_stat);
2377 ADD(0, __NR_statfs);
2378 ADD(0, __NR_symlink);
2379 ADD(0, __NR_sysinfo);
2380 ADD(0, __NR_tgkill);
2381 ADD(0, __NR_time);
2382 ADD(0, __NR_times);
2383 ADD(0, __NR_truncate);
2384# if defined(__NR_truncate64)
2385 ADD(0, __NR_truncate64);
2386# endif
2387# if defined(__NR_ugetrlimit)
2388 ADD(0, __NR_ugetrlimit);
2389# endif
2390 ADD(0, __NR_umask);
2391 ADD(0, __NR_uname);
2392 ADD(0, __NR_unlink);
2393 ADD(0, __NR_utime);
2394# if defined(__NR_waitpid)
2395 ADD(0, __NR_waitpid);
2396# endif
2397 ADD(0, __NR_wait4);
2398 ADD(0, __NR_write);
2399 ADD(0, __NR_writev);
2400
2401 /* Whereas the following need special treatment */
2402# if defined(__NR_arch_prctl)
2403 ADD(1, __NR_arch_prctl);
2404# endif
2405 ADD(1, __NR_brk);
2406 ADD(1, __NR_mmap);
2407# if defined(__NR_mmap2)
2408 ADD(1, __NR_mmap2);
2409# endif
2410# if defined(__NR_shmat)
2411 ADD(1, __NR_shmat);
2412# endif
2413# if defined(__NR_shmget)
2414 ADD(1, __NR_shmget);
2415# endif
2416
2417 /* --------------- AIX5 --------------- */
2418
2419# elif defined(VGO_aix5)
2420
2421# define ADD(_flag, _syscallname) \
2422 do { \
2423 UWordPair p; \
2424 if ((_syscallname) != __NR_AIX5_UNKNOWN) { \
2425 p.uw1 = (UWord)&(_syscallname); p.uw2 = (_flag); \
2426 VG_(addToXA)( post_syscall_table, &p ); \
2427 } \
2428 } while (0)
2429
2430 /* Just a minimal set of handlers, enough to make
2431 a 32- and 64-bit hello-world program run. */
2432 ADD(1, __NR_AIX5___loadx); /* not sure what to do here */
2433 ADD(0, __NR_AIX5__exit);
2434 ADD(0, __NR_AIX5_access);
2435 ADD(0, __NR_AIX5_getgidx);
2436 ADD(0, __NR_AIX5_getuidx);
2437 ADD(0, __NR_AIX5_kfcntl);
2438 ADD(0, __NR_AIX5_kioctl);
2439 ADD(1, __NR_AIX5_kload); /* not sure what to do here */
2440 ADD(0, __NR_AIX5_kwrite);
2441
2442# else
2443# error "Unsupported OS"
2444# endif
2445
2446# undef ADD
2447}
2448
2449
2450void h_post_syscall ( ThreadId tid, UInt sysno, SysRes res )
2451{
2452 Word i, n;
2453 UWordPair* pair;
2454
2455 if (!post_syscall_table)
2456 setup_post_syscall_table();
2457
2458 /* search for 'sysno' in the post_syscall_table */
2459 n = VG_(sizeXA)( post_syscall_table );
2460 for (i = 0; i < n; i++) {
2461 pair = VG_(indexXA)( post_syscall_table, i );
2462# if defined(VGO_linux)
2463 if (pair->uw1 == (UWord)sysno)
2464 break;
2465# elif defined(VGO_aix5)
2466 if (*(Int*)(pair->uw1) == (Int)sysno)
2467 break;
2468# else
2469# error "Unsupported OS"
2470# endif
2471 }
2472
2473 tl_assert(i >= 0 && i <= n);
2474
2475 if (i == n) {
2476 VG_(printf)("sysno == %u\n", sysno);
2477# if defined(VGO_aix5)
2478 VG_(printf)("syscallnm == %s\n",
2479 VG_(aix5_sysno_to_sysname)(sysno));
2480# endif
2481 VG_(tool_panic)("unhandled syscall");
2482 }
2483
2484 /* So we found the relevant entry. Move it one step
2485 forward so as to speed future accesses to it. */
2486 if (i > 0) {
2487 UWordPair tmp, *p, *q;
2488 p = VG_(indexXA)( post_syscall_table, i-1 );
2489 q = VG_(indexXA)( post_syscall_table, i-0 );
2490 tmp = *p;
2491 *p = *q;
2492 *q = tmp;
2493 i--;
2494 }
2495
2496 /* Deal with the common case */
2497 pair = VG_(indexXA)( post_syscall_table, i );
2498 if (pair->uw2 == 0) {
2499 /* the common case */
2500 VG_(set_syscall_return_shadows)(
2501 tid, /* retval */ (UWord)NONPTR, 0,
2502 /* error */ (UWord)NONPTR, 0
2503 );
2504 return;
2505 }
2506
2507 /* Special handling for all remaining cases */
2508 tl_assert(pair->uw2 == 1);
2509
2510# if defined(__NR_arch_prctl)
2511 if (sysno == __NR_arch_prctl) {
2512 /* This is nasty. On amd64-linux, arch_prctl may write a
2513 value to guest_FS_ZERO, and we need to shadow that value.
2514 Hence apply nonptr_or_unknown to it here, after the
2515 syscall completes. */
2516 post_reg_write_nonptr_or_unknown( tid, PC_OFF_FS_ZERO,
2517 PC_SZB_FS_ZERO );
2518 VG_(set_syscall_return_shadows)(
2519 tid, /* retval */ (UWord)NONPTR, 0,
2520 /* error */ (UWord)NONPTR, 0
2521 );
2522 return;
2523 }
2524# endif
2525
2526# if defined(__NR_brk)
2527 // With brk(), result (of kernel syscall, not glibc wrapper) is a heap
2528 // pointer. Make the shadow UNKNOWN.
2529 if (sysno == __NR_brk) {
2530 VG_(set_syscall_return_shadows)(
2531 tid, /* retval */ (UWord)UNKNOWN, 0,
2532 /* error */ (UWord)NONPTR, 0
2533 );
2534 return;
2535 }
2536# endif
2537
2538 // With mmap, new_mem_mmap() has already been called and added the
2539 // segment (we did it there because we had the result address and size
2540 // handy). So just set the return value shadow.
2541 if (sysno == __NR_mmap
2542# if defined(__NR_mmap2)
2543 || sysno == __NR_mmap2
2544# endif
2545# if defined(__NR_AIX5___loadx)
2546 || (sysno == __NR_AIX5___loadx && __NR_AIX5___loadx != __NR_AIX5_UNKNOWN)
2547# endif
2548# if defined(__NR_AIX5_kload)
2549 || (sysno == __NR_AIX5_kload && __NR_AIX5_kload != __NR_AIX5_UNKNOWN)
2550# endif
2551 ) {
njncda2f0f2009-05-18 02:12:08 +00002552 if (sr_isError(res)) {
sewardj024598e2008-09-18 14:43:05 +00002553 // mmap() had an error, return value is a small negative integer
2554 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2555 /*err*/ (UWord)NONPTR, 0 );
2556 if (0) VG_(printf)("ZZZZZZZ mmap res -> NONPTR\n");
2557 } else {
2558 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2559 /*err*/ (UWord)NONPTR, 0 );
2560 if (0) VG_(printf)("ZZZZZZZ mmap res -> UNKNOWN\n");
2561 }
2562 return;
2563 }
2564
2565 // shmat uses the same scheme. We will just have had a
2566 // notification via new_mem_mmap. Just set the return value shadow.
2567# if defined(__NR_shmat)
2568 if (sysno == __NR_shmat) {
njncda2f0f2009-05-18 02:12:08 +00002569 if (sr_isError(res)) {
sewardj024598e2008-09-18 14:43:05 +00002570 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)NONPTR, 0,
2571 /*err*/ (UWord)NONPTR, 0 );
2572 if (0) VG_(printf)("ZZZZZZZ shmat res -> NONPTR\n");
2573 } else {
2574 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2575 /*err*/ (UWord)NONPTR, 0 );
2576 if (0) VG_(printf)("ZZZZZZZ shmat res -> UNKNOWN\n");
2577 }
2578 return;
2579 }
2580# endif
2581
2582# if defined(__NR_shmget)
2583 if (sysno == __NR_shmget) {
2584 // FIXME: is this correct?
2585 VG_(set_syscall_return_shadows)( tid, /*val*/ (UWord)UNKNOWN, 0,
2586 /*err*/ (UWord)NONPTR, 0 );
2587 return;
2588 }
2589# endif
2590
2591 /* If we get here, it implies the corresponding entry in
2592 post_syscall_table has .w2 == 1, which in turn implies there
2593 should be special-case code for it above. */
2594 tl_assert(0);
2595}
2596
2597
2598/*--------------------------------------------------------------------*/
2599/*--- Functions called from generated code ---*/
2600/*--------------------------------------------------------------------*/
2601
2602#if SC_SEGS
2603static void checkSeg ( Seg vseg ) {
2604 tl_assert(vseg == UNKNOWN || vseg == NONPTR || vseg == BOTTOM
2605 || Seg__plausible(vseg) );
2606}
2607#endif
2608
2609// XXX: could be more sophisticated -- actually track the lowest/highest
2610// valid address used by the program, and then return False for anything
2611// below that (using a suitable safety margin). Also, nothing above
2612// 0xc0000000 is valid [unless you've changed that in your kernel]
2613static inline Bool looks_like_a_pointer(Addr a)
2614{
2615# if defined(VGA_x86) || defined(VGA_ppc32)
2616 tl_assert(sizeof(UWord) == 4);
2617 return (a > 0x01000000UL && a < 0xFF000000UL);
2618# elif defined(VGA_amd64) || defined(VGA_ppc64)
2619 tl_assert(sizeof(UWord) == 8);
2620 return (a >= 16 * 0x10000UL && a < 0xFF00000000000000UL);
2621# else
2622# error "Unsupported architecture"
2623# endif
2624}
2625
2626static inline VG_REGPARM(1)
2627Seg* nonptr_or_unknown(UWord x)
2628{
2629 Seg* res = looks_like_a_pointer(x) ? UNKNOWN : NONPTR;
2630 if (0) VG_(printf)("nonptr_or_unknown %s %#lx\n",
2631 res==UNKNOWN ? "UUU" : "nnn", x);
2632 return res;
2633}
2634
2635//zz static __attribute__((regparm(1)))
2636//zz void print_BB_entry(UInt bb)
2637//zz {
2638//zz VG_(printf)("%u =\n", bb);
2639//zz }
2640
sewardj59347ff2008-12-23 02:31:22 +00002641//static ULong stats__tot_mem_refs = 0;
2642//static ULong stats__refs_in_a_seg = 0;
2643//static ULong stats__refs_lost_seg = 0;
sewardj024598e2008-09-18 14:43:05 +00002644
2645typedef
2646 struct { ExeContext* ec; UWord count; }
2647 Lossage;
2648
2649static OSet* lossage = NULL;
2650
sewardj59347ff2008-12-23 02:31:22 +00002651//static void inc_lossage ( ExeContext* ec )
2652//{
2653// Lossage key, *res, *nyu;
2654// key.ec = ec;
2655// key.count = 0; /* frivolous */
2656// res = VG_(OSetGen_Lookup)(lossage, &key);
2657// if (res) {
2658// tl_assert(res->ec == ec);
2659// res->count++;
2660// } else {
2661// nyu = (Lossage*)VG_(OSetGen_AllocNode)(lossage, sizeof(Lossage));
2662// tl_assert(nyu);
2663// nyu->ec = ec;
2664// nyu->count = 1;
2665// VG_(OSetGen_Insert)( lossage, nyu );
2666// }
2667//}
sewardj024598e2008-09-18 14:43:05 +00002668
2669static void init_lossage ( void )
2670{
2671 lossage = VG_(OSetGen_Create)( /*keyOff*/ offsetof(Lossage,ec),
2672 /*fastCmp*/NULL,
2673 VG_(malloc), "pc.h_main.il.1",
2674 VG_(free) );
2675 tl_assert(lossage);
2676}
2677
sewardj59347ff2008-12-23 02:31:22 +00002678//static void show_lossage ( void )
2679//{
2680// Lossage* elem;
2681// VG_(OSetGen_ResetIter)( lossage );
2682// while ( (elem = VG_(OSetGen_Next)(lossage)) ) {
2683// if (elem->count < 10) continue;
2684// //Char buf[100];
2685// //(void)VG_(describe_IP)(elem->ec, buf, sizeof(buf)-1);
2686// //buf[sizeof(buf)-1] = 0;
2687// //VG_(printf)(" %,8lu %s\n", elem->count, buf);
2688// VG_(message)(Vg_UserMsg, "Lossage count %'lu at", elem->count);
2689// VG_(pp_ExeContext)(elem->ec);
2690// }
2691//}
sewardj024598e2008-09-18 14:43:05 +00002692
2693// This function is called *a lot*; inlining it sped up Konqueror by 20%.
2694static inline
2695void check_load_or_store(Bool is_write, Addr m, UWord sz, Seg* mptr_vseg)
2696{
sewardj024598e2008-09-18 14:43:05 +00002697#if 0
sewardj4815eb52008-10-20 23:33:49 +00002698 tl_assert(0);
2699 if (h_clo_lossage_check) {
sewardj024598e2008-09-18 14:43:05 +00002700 Seg* seg;
2701 stats__tot_mem_refs++;
2702 if (ISList__findI0( seglist, (Addr)m, &seg )) {
2703 /* m falls inside 'seg' (that is, we are making a memory
2704 reference inside 'seg'). Now, really mptr_vseg should be
2705 a tracked segment of some description. Badness is when
2706 mptr_vseg is UNKNOWN, BOTTOM or NONPTR at this point,
2707 since that means we've lost the type of it somehow: it
2708 shoud say that m points into a real segment (preferable
2709 'seg'), but it doesn't. */
2710 if (Seg__status_is_SegHeap(seg)) {
2711 stats__refs_in_a_seg++;
2712 if (UNKNOWN == mptr_vseg
2713 || BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
2714 ExeContext* ec;
2715 Char buf[100];
2716 static UWord xx = 0;
2717 stats__refs_lost_seg++;
2718 ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
2719 inc_lossage(ec);
2720 if (0) {
2721 VG_(message)(Vg_DebugMsg, "");
2722 VG_(message)(Vg_DebugMsg,
2723 "Lossage %s %#lx sz %lu inside block alloc'd",
2724 is_write ? "wr" : "rd", m, (UWord)sz);
2725 VG_(pp_ExeContext)(Seg__where(seg));
2726 }
2727 if (xx++ < 0) {
2728 Addr ip = VG_(get_IP)( VG_(get_running_tid)() );
2729 (void)VG_(describe_IP)( ip, buf, sizeof(buf)-1);
2730 buf[sizeof(buf)-1] = 0;
2731 VG_(printf)("lossage at %p %s\n", ec, buf );
2732 }
2733 }
2734 }
2735 }
sewardj024598e2008-09-18 14:43:05 +00002736 } /* clo_lossage_check */
sewardj4815eb52008-10-20 23:33:49 +00002737#endif
sewardj024598e2008-09-18 14:43:05 +00002738
2739# if SC_SEGS
2740 checkSeg(mptr_vseg);
2741# endif
2742
2743 if (UNKNOWN == mptr_vseg) {
2744 // do nothing
2745
2746 } else if (BOTTOM == mptr_vseg) {
2747 // do nothing
2748
2749 } else if (NONPTR == mptr_vseg) {
2750 h_record_heap_error( m, sz, mptr_vseg, is_write );
2751
2752 } else {
2753 // check all segment ranges in the circle
2754 // if none match, warn about 1st seg
2755 // else, check matching one isn't freed
2756 Bool is_ok = False;
2757 Seg* curr = mptr_vseg;
2758 Addr mhi;
2759
2760 // Accesses partly outside range are an error, unless it's an aligned
2761 // word-sized read, and --partial-loads-ok=yes. This is to cope with
2762 // gcc's/glibc's habits of doing word-sized accesses that read past
2763 // the ends of arrays/strings.
2764 // JRS 2008-sept-11: couldn't this be moved off the critical path?
2765 if (!is_write && sz == sizeof(UWord)
2766 && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
2767 mhi = m;
2768 } else {
2769 mhi = m+sz-1;
2770 }
2771
2772 if (0) VG_(printf)("calling seg_ci %p %#lx %#lx\n", curr,m,mhi);
2773 is_ok = curr->addr <= m && mhi < curr->addr + curr->szB;
2774
2775 // If it's an overrun/underrun of a freed block, don't give both
2776 // warnings, since the first one mentions that the block has been
2777 // freed.
2778 if ( ! is_ok || Seg__is_freed(curr) )
2779 h_record_heap_error( m, sz, mptr_vseg, is_write );
2780 }
2781}
2782
2783// ------------------ Load handlers ------------------ //
2784
2785/* On 32 bit targets, we will use:
2786 check_load1 check_load2 check_load4_P
2787 check_load4 (for 32-bit FP reads)
2788 check_load8 (for 64-bit FP reads)
2789 check_load16 (for xmm/altivec reads)
2790 On 64 bit targets, we will use:
2791 check_load1 check_load2 check_load4 check_load8_P
2792 check_load8 (for 64-bit FP reads)
2793 check_load16 (for xmm/altivec reads)
2794
2795 A "_P" handler reads a pointer from memory, and so returns a value
2796 to the generated code -- the pointer's shadow value. That implies
2797 that check_load4_P is only to be called on a 32 bit host and
2798 check_load8_P is only to be called on a 64 bit host. For all other
2799 cases no shadow value is returned; we merely check that the pointer
2800 (m) matches the block described by its shadow value (mptr_vseg).
2801*/
2802
2803// This handles 128 bit loads on both 32 bit and 64 bit targets.
2804static VG_REGPARM(2)
2805void check_load16(Addr m, Seg* mptr_vseg)
2806{
2807# if SC_SEGS
2808 checkSeg(mptr_vseg);
2809# endif
2810 check_load_or_store(/*is_write*/False, m, 16, mptr_vseg);
2811}
2812
2813// This handles 64 bit FP-or-otherwise-nonpointer loads on both
2814// 32 bit and 64 bit targets.
2815static VG_REGPARM(2)
2816void check_load8(Addr m, Seg* mptr_vseg)
2817{
2818# if SC_SEGS
2819 checkSeg(mptr_vseg);
2820# endif
2821 check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2822}
2823
2824// This handles 64 bit loads on 64 bit targets. It must
2825// not be called on 32 bit targets.
2826// return m.vseg
2827static VG_REGPARM(2)
2828Seg* check_load8_P(Addr m, Seg* mptr_vseg)
2829{
2830 Seg* vseg;
2831 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2832# if SC_SEGS
2833 checkSeg(mptr_vseg);
2834# endif
2835 check_load_or_store(/*is_write*/False, m, 8, mptr_vseg);
2836 if (VG_IS_8_ALIGNED(m)) {
2837 vseg = get_mem_vseg(m);
2838 } else {
2839 vseg = nonptr_or_unknown( *(ULong*)m );
2840 }
2841 return vseg;
2842}
2843
2844// This handles 32 bit loads on 32 bit targets. It must
2845// not be called on 64 bit targets.
2846// return m.vseg
2847static VG_REGPARM(2)
2848Seg* check_load4_P(Addr m, Seg* mptr_vseg)
2849{
2850 Seg* vseg;
2851 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2852# if SC_SEGS
2853 checkSeg(mptr_vseg);
2854# endif
2855 check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2856 if (VG_IS_4_ALIGNED(m)) {
2857 vseg = get_mem_vseg(m);
2858 } else {
2859 vseg = nonptr_or_unknown( *(UInt*)m );
2860 }
2861 return vseg;
2862}
2863
2864// Used for both 32 bit and 64 bit targets.
2865static VG_REGPARM(2)
2866void check_load4(Addr m, Seg* mptr_vseg)
2867{
2868# if SC_SEGS
2869 checkSeg(mptr_vseg);
2870# endif
2871 check_load_or_store(/*is_write*/False, m, 4, mptr_vseg);
2872}
2873
2874// Used for both 32 bit and 64 bit targets.
2875static VG_REGPARM(2)
2876void check_load2(Addr m, Seg* mptr_vseg)
2877{
2878# if SC_SEGS
2879 checkSeg(mptr_vseg);
2880# endif
2881 check_load_or_store(/*is_write*/False, m, 2, mptr_vseg);
2882}
2883
2884// Used for both 32 bit and 64 bit targets.
2885static VG_REGPARM(2)
2886void check_load1(Addr m, Seg* mptr_vseg)
2887{
2888# if SC_SEGS
2889 checkSeg(mptr_vseg);
2890# endif
2891 check_load_or_store(/*is_write*/False, m, 1, mptr_vseg);
2892}
2893
2894// ------------------ Store handlers ------------------ //
2895
2896/* On 32 bit targets, we will use:
2897 check_store1 check_store2 check_store4_P
2898 check_store4 (for 32-bit nonpointer stores)
2899 check_store8_ms4B_ls4B (for 64-bit stores)
2900 check_store16_ms4B_4B_4B_ls4B (for xmm/altivec stores)
2901
2902 On 64 bit targets, we will use:
2903 check_store1 check_store2 check_store4 check_store8_P
2904 check_store8_all8B (for 64-bit nonpointer stores)
2905 check_store16_ms8B_ls8B (for xmm/altivec stores)
2906
2907 A "_P" handler writes a pointer to memory, and so has an extra
2908 argument -- the pointer's shadow value. That implies that
2909 check_store4_P is only to be called on a 32 bit host and
2910 check_store8_P is only to be called on a 64 bit host. For all
2911 other cases, and for the misaligned _P cases, the strategy is to
2912 let the store go through, and then snoop around with
2913 nonptr_or_unknown to fix up the shadow values of any affected
2914 words. */
2915
2916/* Apply nonptr_or_unknown to all the words intersecting
2917 [a, a+len). */
2918static VG_REGPARM(2)
2919void nonptr_or_unknown_range ( Addr a, SizeT len )
2920{
2921 const SizeT wszB = sizeof(UWord);
2922 Addr wfirst = VG_ROUNDDN(a, wszB);
2923 Addr wlast = VG_ROUNDDN(a+len-1, wszB);
2924 Addr a2;
2925 tl_assert(wfirst <= wlast);
2926 for (a2 = wfirst ; a2 <= wlast; a2 += wszB) {
2927 set_mem_vseg( a2, nonptr_or_unknown( *(UWord*)a2 ));
2928 }
2929}
2930
2931// This handles 128 bit stores on 64 bit targets. The
2932// store data is passed in 2 pieces, the most significant
2933// bits first.
2934static VG_REGPARM(3)
2935void check_store16_ms8B_ls8B(Addr m, Seg* mptr_vseg,
2936 UWord ms8B, UWord ls8B)
2937{
2938 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
2939# if SC_SEGS
2940 checkSeg(mptr_vseg);
2941# endif
2942 check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2943 // Actually *do* the STORE here
2944 if (host_is_little_endian()) {
2945 // FIXME: aren't we really concerned whether the guest
2946 // is little endian, not whether the host is?
2947 *(ULong*)(m + 0) = ls8B;
2948 *(ULong*)(m + 8) = ms8B;
2949 } else {
2950 *(ULong*)(m + 0) = ms8B;
2951 *(ULong*)(m + 8) = ls8B;
2952 }
2953 nonptr_or_unknown_range(m, 16);
2954}
2955
2956// This handles 128 bit stores on 64 bit targets. The
2957// store data is passed in 2 pieces, the most significant
2958// bits first.
2959static VG_REGPARM(3)
2960void check_store16_ms4B_4B_4B_ls4B(Addr m, Seg* mptr_vseg,
2961 UWord ms4B, UWord w2,
2962 UWord w1, UWord ls4B)
2963{
2964 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2965# if SC_SEGS
2966 checkSeg(mptr_vseg);
2967# endif
2968 check_load_or_store(/*is_write*/True, m, 16, mptr_vseg);
2969 // Actually *do* the STORE here
2970 if (host_is_little_endian()) {
2971 // FIXME: aren't we really concerned whether the guest
2972 // is little endian, not whether the host is?
2973 *(UInt*)(m + 0) = ls4B;
2974 *(UInt*)(m + 4) = w1;
2975 *(UInt*)(m + 8) = w2;
2976 *(UInt*)(m + 12) = ms4B;
2977 } else {
2978 *(UInt*)(m + 0) = ms4B;
2979 *(UInt*)(m + 4) = w2;
2980 *(UInt*)(m + 8) = w1;
2981 *(UInt*)(m + 12) = ls4B;
2982 }
2983 nonptr_or_unknown_range(m, 16);
2984}
2985
2986// This handles 64 bit stores on 32 bit targets. The
2987// store data is passed in 2 pieces, the most significant
2988// bits first.
2989static VG_REGPARM(3)
2990void check_store8_ms4B_ls4B(Addr m, Seg* mptr_vseg,
2991 UWord ms4B, UWord ls4B)
2992{
2993 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
2994# if SC_SEGS
2995 checkSeg(mptr_vseg);
2996# endif
2997 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
2998 // Actually *do* the STORE here
2999 if (host_is_little_endian()) {
3000 // FIXME: aren't we really concerned whether the guest
3001 // is little endian, not whether the host is?
3002 *(UInt*)(m + 0) = ls4B;
3003 *(UInt*)(m + 4) = ms4B;
3004 } else {
3005 *(UInt*)(m + 0) = ms4B;
3006 *(UInt*)(m + 4) = ls4B;
3007 }
3008 nonptr_or_unknown_range(m, 8);
3009}
3010
3011// This handles 64 bit non pointer stores on 64 bit targets.
3012// It must not be called on 32 bit targets.
3013static VG_REGPARM(3)
3014void check_store8_all8B(Addr m, Seg* mptr_vseg, UWord all8B)
3015{
3016 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3017# if SC_SEGS
3018 checkSeg(mptr_vseg);
3019# endif
3020 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3021 // Actually *do* the STORE here
3022 *(ULong*)m = all8B;
3023 nonptr_or_unknown_range(m, 8);
3024}
3025
3026// This handles 64 bit stores on 64 bit targets. It must
3027// not be called on 32 bit targets.
3028static VG_REGPARM(3)
3029void check_store8_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3030{
3031 tl_assert(sizeof(UWord) == 8); /* DO NOT REMOVE */
3032# if SC_SEGS
3033 checkSeg(t_vseg);
3034 checkSeg(mptr_vseg);
3035# endif
3036 check_load_or_store(/*is_write*/True, m, 8, mptr_vseg);
3037 // Actually *do* the STORE here
3038 *(ULong*)m = t;
3039 if (VG_IS_8_ALIGNED(m)) {
3040 set_mem_vseg( m, t_vseg );
3041 } else {
3042 // straddling two words
3043 nonptr_or_unknown_range(m, 8);
3044 }
3045}
3046
3047// This handles 32 bit stores on 32 bit targets. It must
3048// not be called on 64 bit targets.
3049static VG_REGPARM(3)
3050void check_store4_P(Addr m, Seg* mptr_vseg, UWord t, Seg* t_vseg)
3051{
3052 tl_assert(sizeof(UWord) == 4); /* DO NOT REMOVE */
3053# if SC_SEGS
3054 checkSeg(t_vseg);
3055 checkSeg(mptr_vseg);
3056# endif
3057 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3058 // Actually *do* the STORE here
3059 *(UInt*)m = t;
3060 if (VG_IS_4_ALIGNED(m)) {
3061 set_mem_vseg( m, t_vseg );
3062 } else {
3063 // straddling two words
3064 nonptr_or_unknown_range(m, 4);
3065 }
3066}
3067
3068// Used for both 32 bit and 64 bit targets.
3069static VG_REGPARM(3)
3070void check_store4(Addr m, Seg* mptr_vseg, UWord t)
3071{
3072# if SC_SEGS
3073 checkSeg(mptr_vseg);
3074# endif
3075 check_load_or_store(/*is_write*/True, m, 4, mptr_vseg);
3076 // Actually *do* the STORE here (Nb: cast must be to 4-byte type!)
3077 *(UInt*)m = t;
3078 nonptr_or_unknown_range(m, 4);
3079}
3080
3081// Used for both 32 bit and 64 bit targets.
3082static VG_REGPARM(3)
3083void check_store2(Addr m, Seg* mptr_vseg, UWord t)
3084{
3085# if SC_SEGS
3086 checkSeg(mptr_vseg);
3087# endif
3088 check_load_or_store(/*is_write*/True, m, 2, mptr_vseg);
3089 // Actually *do* the STORE here (Nb: cast must be to 2-byte type!)
3090 *(UShort*)m = t;
3091 nonptr_or_unknown_range(m, 2);
3092}
3093
3094// Used for both 32 bit and 64 bit targets.
3095static VG_REGPARM(3)
3096void check_store1(Addr m, Seg* mptr_vseg, UWord t)
3097{
3098# if SC_SEGS
3099 checkSeg(mptr_vseg);
3100# endif
3101 check_load_or_store(/*is_write*/True, m, 1, mptr_vseg);
3102 // Actually *do* the STORE here (Nb: cast must be to 1-byte type!)
3103 *(UChar*)m = t;
3104 nonptr_or_unknown_range(m, 1);
3105}
3106
3107
3108// Nb: if the result is BOTTOM, return immedately -- don't let BOTTOM
3109// be changed to NONPTR by a range check on the result.
3110#define BINOP(bt, nn, nu, np, un, uu, up, pn, pu, pp) \
3111 if (BOTTOM == seg1 || BOTTOM == seg2) { bt; \
3112 } else if (NONPTR == seg1) { if (NONPTR == seg2) { nn; } \
3113 else if (UNKNOWN == seg2) { nu; } \
3114 else { np; } \
3115 } else if (UNKNOWN == seg1) { if (NONPTR == seg2) { un; } \
3116 else if (UNKNOWN == seg2) { uu; } \
3117 else { up; } \
3118 } else { if (NONPTR == seg2) { pn; } \
3119 else if (UNKNOWN == seg2) { pu; } \
3120 else { pp; } \
3121 }
3122
3123#define BINERROR(opname) \
3124 h_record_arith_error(seg1, seg2, opname); \
3125 out = NONPTR
3126
3127
3128// -------------
3129// + | n ? p
3130// -------------
3131// n | n ? p
3132// ? | ? ? ?
3133// p | p ? e (all results become n if they look like a non-pointer)
3134// -------------
3135static Seg* do_addW_result(Seg* seg1, Seg* seg2, UWord result, HChar* opname)
3136{
3137 Seg* out;
3138# if SC_SEGS
3139 checkSeg(seg1);
3140 checkSeg(seg2);
3141# endif
3142 BINOP(
3143 return BOTTOM,
3144 out = NONPTR, out = UNKNOWN, out = seg2,
3145 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3146 out = seg1, out = UNKNOWN, BINERROR(opname)
3147 );
3148 return ( looks_like_a_pointer(result) ? out : NONPTR );
3149}
3150
3151static VG_REGPARM(3) Seg* do_addW(Seg* seg1, Seg* seg2, UWord result)
3152{
3153 Seg* out;
3154# if SC_SEGS
3155 checkSeg(seg1);
3156 checkSeg(seg2);
3157# endif
3158 out = do_addW_result(seg1, seg2, result, "Add32/Add64");
3159# if SC_SEGS
3160 checkSeg(out);
3161# endif
3162 return out;
3163}
3164
3165// -------------
3166// - | n ? p (Nb: operation is seg1 - seg2)
3167// -------------
3168// n | n ? n+ (+) happens a lot due to "cmp", but result should never
3169// ? | ? ? n/B be used, so give 'n'
3170// p | p p? n*/B (*) and possibly link the segments
3171// -------------
3172static VG_REGPARM(3) Seg* do_subW(Seg* seg1, Seg* seg2, UWord result)
3173{
3174 Seg* out;
3175# if SC_SEGS
3176 checkSeg(seg1);
3177 checkSeg(seg2);
3178# endif
3179 // Nb: when returning BOTTOM, don't let it go through the range-check;
3180 // a segment linking offset can easily look like a nonptr.
3181 BINOP(
3182 return BOTTOM,
3183 out = NONPTR, out = UNKNOWN, out = NONPTR,
3184 out = UNKNOWN, out = UNKNOWN, return BOTTOM,
3185 out = seg1, out = seg1/*??*/, return BOTTOM
3186 );
3187 #if 0
3188 // This is for the p-p segment-linking case
3189 Seg end2 = seg2;
3190 while (end2->links != seg2) end2 = end2->links;
3191 end2->links = seg1->links;
3192 seg1->links = seg2;
3193 return NONPTR;
3194 #endif
3195 return ( looks_like_a_pointer(result) ? out : NONPTR );
3196}
3197
3198// -------------
3199// & | n ? p
3200// -------------
3201// n | n ? p
3202// ? | ? ? ?
3203// p | p ? * (*) if p1==p2 then p else e (see comment)
3204// -------------
3205/* Seems to be OK to And two pointers:
3206 testq %ptr1,%ptr2
3207 jnz ..
3208 which possibly derives from
3209 if (ptr1 & ptr2) { A } else { B }
3210 not sure what that means
3211*/
3212static VG_REGPARM(3) Seg* do_andW(Seg* seg1, Seg* seg2,
3213 UWord result, UWord args_diff)
3214{
3215 Seg* out;
3216 if (0 == args_diff) {
3217 // p1==p2
3218 out = seg1;
3219 } else {
3220 BINOP(
3221 return BOTTOM,
3222 out = NONPTR, out = UNKNOWN, out = seg2,
3223 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3224 out = seg1, out = UNKNOWN, out = NONPTR
3225 /*BINERROR("And32/And64")*/
3226 );
3227 }
3228 out = ( looks_like_a_pointer(result) ? out : NONPTR );
3229 return out;
3230}
3231
3232// -------------
3233// `|`| n ? p
3234// -------------
3235// n | n ? p
3236// ? | ? ? ?
3237// p | p ? n
3238// -------------
3239/* It's OK to Or two pointers together, but the result definitely
3240 isn't a pointer. Why would you want to do that? Because of this:
3241 char* p1 = malloc(..);
3242 char* p2 = malloc(..);
3243 ...
3244 if (p1 || p2) { .. }
3245 In this case gcc on x86/amd64 quite literally or-s the two pointers
3246 together and throws away the result, the purpose of which is merely
3247 to sets %eflags.Z/%rflags.Z. So we have to allow it.
3248*/
3249static VG_REGPARM(3) Seg* do_orW(Seg* seg1, Seg* seg2, UWord result)
3250{
3251 Seg* out;
3252 BINOP(
3253 return BOTTOM,
3254 out = NONPTR, out = UNKNOWN, out = seg2,
3255 out = UNKNOWN, out = UNKNOWN, out = UNKNOWN,
3256 out = seg1, out = UNKNOWN, out = NONPTR
3257 );
3258 out = ( looks_like_a_pointer(result) ? out : NONPTR );
3259 return out;
3260}
3261
3262// -------------
3263// ~ | n ? p
3264// -------------
3265// | n n n
3266// -------------
3267static VG_REGPARM(2) Seg* do_notW(Seg* seg1, UWord result)
3268{
3269# if SC_SEGS
3270 checkSeg(seg1);
3271# endif
3272 if (BOTTOM == seg1) return BOTTOM;
3273 return NONPTR;
3274}
3275
3276// Pointers are rarely multiplied, but sometimes legitimately, eg. as hash
3277// function inputs. But two pointers args --> error.
3278// Pretend it always returns a nonptr. Maybe improve later.
3279static VG_REGPARM(2) Seg* do_mulW(Seg* seg1, Seg* seg2)
3280{
3281# if SC_SEGS
3282 checkSeg(seg1);
3283 checkSeg(seg2);
3284# endif
3285 if (is_known_segment(seg1) && is_known_segment(seg2))
3286 h_record_arith_error(seg1, seg2, "Mul32/Mul64");
3287 return NONPTR;
3288}
3289
3290
3291/*--------------------------------------------------------------------*/
3292/*--- Instrumentation ---*/
3293/*--------------------------------------------------------------------*/
3294
3295/* The h_ instrumenter that follows is complex, since it deals with
3296 shadow value computation.
3297
3298 It also needs to generate instrumentation for the sg_ side of
3299 things. That's relatively straightforward. However, rather than
3300 confuse the code herein any further, we simply delegate the problem
3301 to sg_main.c, by using the four functions
3302 sg_instrument_{init,fini,IRStmt,final_jump}. These four completely
3303 abstractify the sg_ instrumentation. See comments in sg_main.c's
3304 instrumentation section for further details. */
3305
3306/* Carries around state during Ptrcheck instrumentation. */
3307typedef
3308 struct {
3309 /* MODIFIED: the superblock being constructed. IRStmts are
3310 added. */
3311 IRSB* bb;
3312 Bool trace;
3313
3314 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
3315 original temps to their current their current shadow temp.
3316 Initially all entries are IRTemp_INVALID. Entries are added
3317 lazily since many original temps are not used due to
3318 optimisation prior to instrumentation. Note that only
3319 integer temps of the guest word size are shadowed, since it
3320 is impossible (or meaningless) to hold a pointer in any other
3321 type of temp. */
3322 IRTemp* tmpMap;
3323 Int n_originalTmps; /* for range checking */
3324
3325 /* READONLY: the host word type. Needed for constructing
3326 arguments of type 'HWord' to be passed to helper functions.
3327 Ity_I32 or Ity_I64 only. */
3328 IRType hWordTy;
3329
3330 /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
3331 IRType gWordTy;
3332
3333 /* READONLY: the guest state size, so we can generate shadow
3334 offsets correctly. */
3335 Int guest_state_sizeB;
3336 }
3337 PCEnv;
3338
3339/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
3340 demand), as they are encountered. This is for two reasons.
3341
3342 (1) (less important reason): Many original tmps are unused due to
3343 initial IR optimisation, and we do not want to spaces in tables
3344 tracking them.
3345
3346 Shadow IRTemps are therefore allocated on demand. pce.tmpMap is a
3347 table indexed [0 .. n_types-1], which gives the current shadow for
3348 each original tmp, or INVALID_IRTEMP if none is so far assigned.
3349 It is necessary to support making multiple assignments to a shadow
3350 -- specifically, after testing a shadow for definedness, it needs
3351 to be made defined. But IR's SSA property disallows this.
3352
3353 (2) (more important reason): Therefore, when a shadow needs to get
3354 a new value, a new temporary is created, the value is assigned to
3355 that, and the tmpMap is updated to reflect the new binding.
3356
3357 A corollary is that if the tmpMap maps a given tmp to
3358 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
3359 there's a read-before-write error in the original tmps. The IR
3360 sanity checker should catch all such anomalies, however.
3361*/
3362
3363/* Find the tmp currently shadowing the given original tmp. If none
3364 so far exists, allocate one. */
3365static IRTemp findShadowTmp ( PCEnv* pce, IRTemp orig )
3366{
3367 tl_assert(orig < pce->n_originalTmps);
3368 tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3369 if (pce->tmpMap[orig] == IRTemp_INVALID) {
3370 tl_assert(0);
3371 pce->tmpMap[orig]
3372 = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3373 }
3374 return pce->tmpMap[orig];
3375}
3376
3377/* Allocate a new shadow for the given original tmp. This means any
3378 previous shadow is abandoned. This is needed because it is
3379 necessary to give a new value to a shadow once it has been tested
3380 for undefinedness, but unfortunately IR's SSA property disallows
3381 this. Instead we must abandon the old shadow, allocate a new one
3382 and use that instead. */
3383__attribute__((noinline))
3384static IRTemp newShadowTmp ( PCEnv* pce, IRTemp orig )
3385{
3386 tl_assert(orig < pce->n_originalTmps);
3387 tl_assert(pce->bb->tyenv->types[orig] == pce->gWordTy);
3388 pce->tmpMap[orig]
3389 = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3390 return pce->tmpMap[orig];
3391}
3392
3393
3394/*------------------------------------------------------------*/
3395/*--- IRAtoms -- a subset of IRExprs ---*/
3396/*------------------------------------------------------------*/
3397
3398/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
3399 isIRAtom() in libvex_ir.h. Because this instrumenter expects flat
3400 input, most of this code deals in atoms. Usefully, a value atom
3401 always has a V-value which is also an atom: constants are shadowed
3402 by constants, and temps are shadowed by the corresponding shadow
3403 temporary. */
3404
3405typedef IRExpr IRAtom;
3406
3407//zz /* (used for sanity checks only): is this an atom which looks
3408//zz like it's from original code? */
3409//zz static Bool isOriginalAtom ( PCEnv* pce, IRAtom* a1 )
3410//zz {
3411//zz if (a1->tag == Iex_Const)
3412//zz return True;
3413//zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < pce->n_originalTmps)
3414//zz return True;
3415//zz return False;
3416//zz }
3417//zz
3418//zz /* (used for sanity checks only): is this an atom which looks
3419//zz like it's from shadow code? */
3420//zz static Bool isShadowAtom ( PCEnv* pce, IRAtom* a1 )
3421//zz {
3422//zz if (a1->tag == Iex_Const)
3423//zz return True;
3424//zz if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= pce->n_originalTmps)
3425//zz return True;
3426//zz return False;
3427//zz }
3428//zz
3429//zz /* (used for sanity checks only): check that both args are atoms and
3430//zz are identically-kinded. */
3431//zz static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
3432//zz {
3433//zz if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
3434//zz return True;
3435//zz if (a1->tag == Iex_Const && a2->tag == Iex_Const)
3436//zz return True;
3437//zz return False;
3438//zz }
3439
3440
3441/*------------------------------------------------------------*/
3442/*--- Constructing IR fragments ---*/
3443/*------------------------------------------------------------*/
3444
3445/* add stmt to a bb */
3446static inline void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
3447 if (pce->trace) {
3448 VG_(printf)(" %c: ", cat);
3449 ppIRStmt(st);
3450 VG_(printf)("\n");
3451 }
3452 addStmtToIRSB(pce->bb, st);
3453}
3454
3455/* assign value to tmp */
3456static inline
3457void assign ( HChar cat, PCEnv* pce, IRTemp tmp, IRExpr* expr ) {
3458 stmt(cat, pce, IRStmt_WrTmp(tmp,expr));
3459}
3460
3461/* build various kinds of expressions */
3462#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
3463#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
3464#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
3465#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
3466#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
3467#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
3468#define mkV128(_n) IRExpr_Const(IRConst_V128(_n))
3469#define mkexpr(_tmp) IRExpr_RdTmp((_tmp))
3470
3471/* Bind the given expression to a new temporary, and return the
3472 temporary. This effectively converts an arbitrary expression into
3473 an atom.
3474
3475 'ty' is the type of 'e' and hence the type that the new temporary
3476 needs to be. But passing it is redundant, since we can deduce the
3477 type merely by inspecting 'e'. So at least that fact to assert
3478 that the two types agree. */
3479static IRAtom* assignNew ( HChar cat, PCEnv* pce, IRType ty, IRExpr* e ) {
3480 IRTemp t;
3481 IRType tyE = typeOfIRExpr(pce->bb->tyenv, e);
3482 tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
3483 t = newIRTemp(pce->bb->tyenv, ty);
3484 assign(cat, pce, t, e);
3485 return mkexpr(t);
3486}
3487
3488
3489
3490//-----------------------------------------------------------------------
3491// Approach taken for range-checking for NONPTR/UNKNOWN-ness as follows.
3492//
3493// Range check (NONPTR/seg):
3494// - after modifying a word-sized value in/into a TempReg:
3495// - {ADD, SUB, ADC, SBB, AND, OR, XOR, LEA, LEA2, NEG, NOT}L
3496// - BSWAP
3497//
3498// Range check (NONPTR/UNKNOWN):
3499// - when introducing a new word-sized value into a TempReg:
3500// - MOVL l, t2
3501//
3502// - when copying a word-sized value which lacks a corresponding segment
3503// into a TempReg:
3504// - straddled LDL
3505//
3506// - when a sub-word of a word (or two) is updated:
3507// - SHROTL
3508// - {ADD, SUB, ADC, SBB, AND, OR, XOR, SHROT, NEG, NOT}[WB]
3509// - PUT[WB]
3510// - straddled STL (2 range checks)
3511// - straddled STW (2 range checks)
3512// - unstraddled STW
3513// - STB
3514//
3515// Just copy:
3516// - when copying word-sized values:
3517// - MOVL t1, t2 (--optimise=no only)
3518// - CMOV
3519// - GETL, PUTL
3520// - unstraddled LDL, unstraddled STL
3521//
3522// - when barely changing
3523// - INC[LWB]/DEC[LWB]
3524//
3525// Set to NONPTR:
3526// - after copying a sub-word value into a TempReg:
3527// - MOV[WB] l, t2
3528// - GET[WB]
3529// - unstraddled LDW
3530// - straddled LDW
3531// - LDB
3532// - POP[WB]
3533//
3534// - after copying an obvious non-ptr into a TempReg:
3535// - GETF
3536// - CC2VAL
3537// - POPL
3538//
3539// - after copying an obvious non-ptr into a memory word:
3540// - FPU_W
3541//
3542// Do nothing:
3543// - LOCK, INCEIP
3544// - WIDEN[WB]
3545// - JMP, JIFZ
3546// - CALLM_[SE], PUSHL, CALLM, CLEAR
3547// - FPU, FPU_R (and similar MMX/SSE ones)
3548//
3549
3550
3551
3552
3553/* Call h_fn (name h_nm) with the given arg, and return a new IRTemp
3554 holding the result. The arg must be a word-typed atom. Callee
3555 must be a VG_REGPARM(1) function. */
3556__attribute__((noinline))
3557static IRTemp gen_dirty_W_W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3558 IRExpr* a1 )
3559{
3560 IRTemp res;
3561 IRDirty* di;
3562 tl_assert(isIRAtom(a1));
3563 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3564 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3565 di = unsafeIRDirty_1_N( res, 1/*regparms*/,
3566 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3567 mkIRExprVec_1( a1 ) );
3568 stmt( 'I', pce, IRStmt_Dirty(di) );
3569 return res;
3570}
3571
3572/* Two-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(2)
3573 function.*/
3574static IRTemp gen_dirty_W_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3575 IRExpr* a1, IRExpr* a2 )
3576{
3577 IRTemp res;
3578 IRDirty* di;
3579 tl_assert(isIRAtom(a1));
3580 tl_assert(isIRAtom(a2));
3581 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3582 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3583 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3584 di = unsafeIRDirty_1_N( res, 2/*regparms*/,
3585 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3586 mkIRExprVec_2( a1, a2 ) );
3587 stmt( 'I', pce, IRStmt_Dirty(di) );
3588 return res;
3589}
3590
3591/* Three-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3)
3592 function.*/
3593static IRTemp gen_dirty_W_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3594 IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3595{
3596 IRTemp res;
3597 IRDirty* di;
3598 tl_assert(isIRAtom(a1));
3599 tl_assert(isIRAtom(a2));
3600 tl_assert(isIRAtom(a3));
3601 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3602 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3603 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3604 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3605 di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3606 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3607 mkIRExprVec_3( a1, a2, a3 ) );
3608 stmt( 'I', pce, IRStmt_Dirty(di) );
3609 return res;
3610}
3611
3612/* Four-arg version of gen_dirty_W_W. Callee must be a VG_REGPARM(3)
3613 function.*/
3614static IRTemp gen_dirty_W_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3615 IRExpr* a1, IRExpr* a2,
3616 IRExpr* a3, IRExpr* a4 )
3617{
3618 IRTemp res;
3619 IRDirty* di;
3620 tl_assert(isIRAtom(a1));
3621 tl_assert(isIRAtom(a2));
3622 tl_assert(isIRAtom(a3));
3623 tl_assert(isIRAtom(a4));
3624 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3625 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3626 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3627 tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3628 res = newIRTemp(pce->bb->tyenv, pce->gWordTy);
3629 di = unsafeIRDirty_1_N( res, 3/*regparms*/,
3630 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3631 mkIRExprVec_4( a1, a2, a3, a4 ) );
3632 stmt( 'I', pce, IRStmt_Dirty(di) );
3633 return res;
3634}
3635
3636/* Version of gen_dirty_W_WW with no return value. Callee must be a
3637 VG_REGPARM(2) function.*/
3638static void gen_dirty_v_WW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3639 IRExpr* a1, IRExpr* a2 )
3640{
3641 IRDirty* di;
3642 tl_assert(isIRAtom(a1));
3643 tl_assert(isIRAtom(a2));
3644 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3645 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3646 di = unsafeIRDirty_0_N( 2/*regparms*/,
3647 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3648 mkIRExprVec_2( a1, a2 ) );
3649 stmt( 'I', pce, IRStmt_Dirty(di) );
3650}
3651
3652/* Version of gen_dirty_W_WWW with no return value. Callee must be a
3653 VG_REGPARM(3) function.*/
3654static void gen_dirty_v_WWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3655 IRExpr* a1, IRExpr* a2, IRExpr* a3 )
3656{
3657 IRDirty* di;
3658 tl_assert(isIRAtom(a1));
3659 tl_assert(isIRAtom(a2));
3660 tl_assert(isIRAtom(a3));
3661 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3662 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3663 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3664 di = unsafeIRDirty_0_N( 3/*regparms*/,
3665 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3666 mkIRExprVec_3( a1, a2, a3 ) );
3667 stmt( 'I', pce, IRStmt_Dirty(di) );
3668}
3669
3670/* Version of gen_dirty_v_WWW for 4 arguments. Callee must be a
3671 VG_REGPARM(3) function.*/
3672static void gen_dirty_v_WWWW ( PCEnv* pce, void* h_fn, HChar* h_nm,
3673 IRExpr* a1, IRExpr* a2,
3674 IRExpr* a3, IRExpr* a4 )
3675{
3676 IRDirty* di;
3677 tl_assert(isIRAtom(a1));
3678 tl_assert(isIRAtom(a2));
3679 tl_assert(isIRAtom(a3));
3680 tl_assert(isIRAtom(a4));
3681 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3682 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3683 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3684 tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3685 di = unsafeIRDirty_0_N( 3/*regparms*/,
3686 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3687 mkIRExprVec_4( a1, a2, a3, a4 ) );
3688 stmt( 'I', pce, IRStmt_Dirty(di) );
3689}
3690
3691/* Version of gen_dirty_v_WWW for 6 arguments. Callee must be a
3692 VG_REGPARM(3) function.*/
3693static void gen_dirty_v_6W ( PCEnv* pce, void* h_fn, HChar* h_nm,
3694 IRExpr* a1, IRExpr* a2, IRExpr* a3,
3695 IRExpr* a4, IRExpr* a5, IRExpr* a6 )
3696{
3697 IRDirty* di;
3698 tl_assert(isIRAtom(a1));
3699 tl_assert(isIRAtom(a2));
3700 tl_assert(isIRAtom(a3));
3701 tl_assert(isIRAtom(a4));
3702 tl_assert(isIRAtom(a5));
3703 tl_assert(isIRAtom(a6));
3704 tl_assert(typeOfIRExpr(pce->bb->tyenv, a1) == pce->gWordTy);
3705 tl_assert(typeOfIRExpr(pce->bb->tyenv, a2) == pce->gWordTy);
3706 tl_assert(typeOfIRExpr(pce->bb->tyenv, a3) == pce->gWordTy);
3707 tl_assert(typeOfIRExpr(pce->bb->tyenv, a4) == pce->gWordTy);
3708 tl_assert(typeOfIRExpr(pce->bb->tyenv, a5) == pce->gWordTy);
3709 tl_assert(typeOfIRExpr(pce->bb->tyenv, a6) == pce->gWordTy);
3710 di = unsafeIRDirty_0_N( 3/*regparms*/,
3711 h_nm, VG_(fnptr_to_fnentry)( h_fn ),
3712 mkIRExprVec_6( a1, a2, a3, a4, a5, a6 ) );
3713 stmt( 'I', pce, IRStmt_Dirty(di) );
3714}
3715
3716static IRAtom* uwiden_to_host_word ( PCEnv* pce, IRAtom* a )
3717{
3718 IRType a_ty = typeOfIRExpr(pce->bb->tyenv, a);
3719 tl_assert(isIRAtom(a));
3720 if (pce->hWordTy == Ity_I32) {
3721 switch (a_ty) {
3722 case Ity_I8:
3723 return assignNew( 'I', pce, Ity_I32, unop(Iop_8Uto32, a) );
3724 case Ity_I16:
3725 return assignNew( 'I', pce, Ity_I32, unop(Iop_16Uto32, a) );
3726 default:
3727 ppIRType(a_ty);
3728 tl_assert(0);
3729 }
3730 } else {
3731 tl_assert(pce->hWordTy == Ity_I64);
3732 switch (a_ty) {
3733 case Ity_I8:
3734 return assignNew( 'I', pce, Ity_I64, unop(Iop_8Uto64, a) );
3735 case Ity_I16:
3736 return assignNew( 'I', pce, Ity_I64, unop(Iop_16Uto64, a) );
3737 case Ity_I32:
3738 return assignNew( 'I', pce, Ity_I64, unop(Iop_32Uto64, a) );
3739 default:
3740 ppIRType(a_ty);
3741 tl_assert(0);
3742 }
3743 }
3744}
3745
3746/* 'e' is a word-sized atom. Call nonptr_or_unknown with it, bind the
3747 results to a new temporary, and return the temporary. Note this
3748 takes an original expression but returns a shadow value. */
3749static IRTemp gen_call_nonptr_or_unknown_w ( PCEnv* pce, IRExpr* e )
3750{
3751 return gen_dirty_W_W( pce, &nonptr_or_unknown,
3752 "nonptr_or_unknown", e );
3753}
3754
3755
3756/* Generate the shadow value for an IRExpr which is an atom and
3757 guaranteed to be word-sized. */
3758static IRAtom* schemeEw_Atom ( PCEnv* pce, IRExpr* e )
3759{
3760 if (pce->gWordTy == Ity_I32) {
3761 if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U32) {
3762 IRTemp t;
3763 tl_assert(sizeof(UWord) == 4);
3764 t = gen_call_nonptr_or_unknown_w(pce, e);
3765 return mkexpr(t);
3766 }
3767 if (e->tag == Iex_RdTmp
3768 && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I32) {
3769 return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3770 }
3771 /* there are no other word-sized atom cases */
3772 } else {
3773 if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U64) {
3774 IRTemp t;
3775 tl_assert(sizeof(UWord) == 8);
3776 //return mkU64( (ULong)(UWord)NONPTR );
3777 t = gen_call_nonptr_or_unknown_w(pce, e);
3778 return mkexpr(t);
3779 }
3780 if (e->tag == Iex_RdTmp
3781 && typeOfIRExpr(pce->bb->tyenv, e) == Ity_I64) {
3782 return mkexpr( findShadowTmp(pce, e->Iex.RdTmp.tmp) );
3783 }
3784 /* there are no other word-sized atom cases */
3785 }
3786 ppIRExpr(e);
3787 tl_assert(0);
3788}
3789
3790
3791static
3792void instrument_arithop ( PCEnv* pce,
3793 IRTemp dst, /* already holds result */
3794 IRTemp dstv, /* generate an assignment to this */
3795 IROp op,
3796 /* original args, guaranteed to be atoms */
3797 IRExpr* a1, IRExpr* a2, IRExpr* a3, IRExpr* a4 )
3798{
3799 HChar* nm = NULL;
3800 void* fn = NULL;
3801 IRExpr* a1v = NULL;
3802 IRExpr* a2v = NULL;
3803 //IRExpr* a3v = NULL;
3804 //IRExpr* a4v = NULL;
3805 IRTemp res = IRTemp_INVALID;
3806
3807 if (pce->gWordTy == Ity_I32) {
3808
3809 tl_assert(pce->hWordTy == Ity_I32);
3810 switch (op) {
3811
3812 /* For these cases, pass Segs for both arguments, and the
3813 result value. */
3814 case Iop_Add32: nm = "do_addW"; fn = &do_addW; goto ssr32;
3815 case Iop_Sub32: nm = "do_subW"; fn = &do_subW; goto ssr32;
3816 case Iop_Or32: nm = "do_orW"; fn = &do_orW; goto ssr32;
3817 ssr32:
3818 a1v = schemeEw_Atom( pce, a1 );
3819 a2v = schemeEw_Atom( pce, a2 );
3820 res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3821 assign( 'I', pce, dstv, mkexpr(res) );
3822 break;
3823
3824 /* In this case, pass Segs for both arguments, the result
3825 value, and the difference between the (original) values of
3826 the arguments. */
3827 case Iop_And32:
3828 nm = "do_andW"; fn = &do_andW;
3829 a1v = schemeEw_Atom( pce, a1 );
3830 a2v = schemeEw_Atom( pce, a2 );
3831 res = gen_dirty_W_WWWW(
3832 pce, fn, nm, a1v, a2v, mkexpr(dst),
3833 assignNew( 'I', pce, Ity_I32,
3834 binop(Iop_Sub32,a1,a2) ) );
3835 assign( 'I', pce, dstv, mkexpr(res) );
3836 break;
3837
3838 /* Pass one shadow arg and the result to the helper. */
3839 case Iop_Not32: nm = "do_notW"; fn = &do_notW; goto vr32;
3840 vr32:
3841 a1v = schemeEw_Atom( pce, a1 );
3842 res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3843 assign( 'I', pce, dstv, mkexpr(res) );
3844 break;
3845
3846 /* Pass two shadow args only to the helper. */
3847 case Iop_Mul32: nm = "do_mulW"; fn = &do_mulW; goto vv32;
3848 vv32:
3849 a1v = schemeEw_Atom( pce, a1 );
3850 a2v = schemeEw_Atom( pce, a2 );
3851 res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3852 assign( 'I', pce, dstv, mkexpr(res) );
3853 break;
3854
3855 /* We don't really know what the result could be; test at run
3856 time. */
3857 case Iop_64HIto32: goto n_or_u_32;
3858 case Iop_64to32: goto n_or_u_32;
3859 case Iop_Xor32: goto n_or_u_32;
3860 n_or_u_32:
3861 assign( 'I', pce, dstv,
3862 mkexpr(
3863 gen_call_nonptr_or_unknown_w( pce,
3864 mkexpr(dst) ) ) );
3865 break;
3866
3867 /* Cases where it's very obvious that the result cannot be a
3868 pointer. Hence declare directly that it's NONPTR; don't
3869 bother with the overhead of calling nonptr_or_unknown. */
3870
3871 /* cases where it makes no sense for the result to be a ptr */
3872 /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3873 arg, so that shift by zero preserves the original
3874 value. */
3875 case Iop_Shl32: goto n32;
3876 case Iop_Sar32: goto n32;
3877 case Iop_Shr32: goto n32;
3878 case Iop_16Uto32: goto n32;
3879 case Iop_16Sto32: goto n32;
3880 case Iop_F64toI32: goto n32;
3881 case Iop_16HLto32: goto n32;
3882 case Iop_MullS16: goto n32;
3883 case Iop_MullU16: goto n32;
3884 case Iop_PRemC3210F64: goto n32;
3885 case Iop_DivU32: goto n32;
3886 case Iop_DivS32: goto n32;
3887 case Iop_V128to32: goto n32;
3888
3889 /* cases where result range is very limited and clearly cannot
3890 be a pointer */
3891 case Iop_1Uto32: goto n32;
3892 case Iop_1Sto32: goto n32;
3893 case Iop_8Uto32: goto n32;
3894 case Iop_8Sto32: goto n32;
3895 case Iop_Clz32: goto n32;
3896 case Iop_Ctz32: goto n32;
3897 case Iop_CmpF64: goto n32;
3898 case Iop_CmpORD32S: goto n32;
3899 case Iop_CmpORD32U: goto n32;
3900 n32:
3901 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
3902 break;
3903
3904 default:
3905 VG_(printf)("instrument_arithop(32-bit): unhandled: ");
3906 ppIROp(op);
3907 tl_assert(0);
3908 }
3909
3910 } else {
3911
3912 tl_assert(pce->gWordTy == Ity_I64);
3913 switch (op) {
3914
3915 /* For these cases, pass Segs for both arguments, and the
3916 result value. */
3917 case Iop_Add64: nm = "do_addW"; fn = &do_addW; goto ssr64;
3918 case Iop_Sub64: nm = "do_subW"; fn = &do_subW; goto ssr64;
3919 case Iop_Or64: nm = "do_orW"; fn = &do_orW; goto ssr64;
3920 ssr64:
3921 a1v = schemeEw_Atom( pce, a1 );
3922 a2v = schemeEw_Atom( pce, a2 );
3923 res = gen_dirty_W_WWW( pce, fn, nm, a1v, a2v, mkexpr(dst) );
3924 assign( 'I', pce, dstv, mkexpr(res) );
3925 break;
3926
3927 /* In this case, pass Segs for both arguments, the result
3928 value, and the difference between the (original) values of
3929 the arguments. */
3930 case Iop_And64:
3931 nm = "do_andW"; fn = &do_andW;
3932 a1v = schemeEw_Atom( pce, a1 );
3933 a2v = schemeEw_Atom( pce, a2 );
3934 res = gen_dirty_W_WWWW(
3935 pce, fn, nm, a1v, a2v, mkexpr(dst),
3936 assignNew( 'I', pce, Ity_I64,
3937 binop(Iop_Sub64,a1,a2) ) );
3938 assign( 'I', pce, dstv, mkexpr(res) );
3939 break;
3940
3941 /* Pass one shadow arg and the result to the helper. */
3942 case Iop_Not64: nm = "do_notW"; fn = &do_notW; goto vr64;
3943 vr64:
3944 a1v = schemeEw_Atom( pce, a1 );
3945 res = gen_dirty_W_WW( pce, fn, nm, a1v, mkexpr(dst) );
3946 assign( 'I', pce, dstv, mkexpr(res) );
3947 break;
3948
3949 /* Pass two shadow args only to the helper. */
3950 case Iop_Mul64: nm = "do_mulW"; fn = &do_mulW; goto vv64;
3951 vv64:
3952 a1v = schemeEw_Atom( pce, a1 );
3953 a2v = schemeEw_Atom( pce, a2 );
3954 res = gen_dirty_W_WW( pce, fn, nm, a1v, a2v );
3955 assign( 'I', pce, dstv, mkexpr(res) );
3956 break;
3957
3958 /* We don't really know what the result could be; test at run
3959 time. */
3960 case Iop_Xor64: goto n_or_u_64;
3961 case Iop_128HIto64: goto n_or_u_64;
3962 case Iop_128to64: goto n_or_u_64;
3963 case Iop_V128HIto64: goto n_or_u_64;
3964 case Iop_V128to64: goto n_or_u_64;
3965 n_or_u_64:
3966 assign( 'I', pce, dstv,
3967 mkexpr(
3968 gen_call_nonptr_or_unknown_w( pce,
3969 mkexpr(dst) ) ) );
3970 break;
3971
3972 /* Cases where it's very obvious that the result cannot be a
3973 pointer. Hence declare directly that it's NONPTR; don't
3974 bother with the overhead of calling nonptr_or_unknown. */
3975
3976 /* cases where it makes no sense for the result to be a ptr */
3977 /* FIXME: for Shl/Shr/Sar, really should do a test on the 2nd
3978 arg, so that shift by zero preserves the original
3979 value. */
3980 case Iop_Shl64: goto n64;
3981 case Iop_Sar64: goto n64;
3982 case Iop_Shr64: goto n64;
3983 case Iop_32Uto64: goto n64;
3984 case Iop_32Sto64: goto n64;
3985 case Iop_16Uto64: goto n64;
3986 case Iop_16Sto64: goto n64;
3987 case Iop_32HLto64: goto n64;
3988 case Iop_DivModU64to32: goto n64;
3989 case Iop_DivModS64to32: goto n64;
3990 case Iop_F64toI64: goto n64;
3991 case Iop_MullS32: goto n64;
3992 case Iop_MullU32: goto n64;
3993 case Iop_DivU64: goto n64;
3994 case Iop_DivS64: goto n64;
3995 case Iop_ReinterpF64asI64: goto n64;
3996
3997 /* cases where result range is very limited and clearly cannot
3998 be a pointer */
3999 case Iop_1Uto64: goto n64;
4000 case Iop_8Uto64: goto n64;
4001 case Iop_8Sto64: goto n64;
4002 case Iop_Ctz64: goto n64;
4003 case Iop_Clz64: goto n64;
4004 case Iop_CmpORD64S: goto n64;
4005 case Iop_CmpORD64U: goto n64;
4006 /* 64-bit simd */
4007 case Iop_Avg8Ux8: case Iop_Avg16Ux4:
4008 case Iop_Max16Sx4: case Iop_Max8Ux8: case Iop_Min16Sx4:
4009 case Iop_Min8Ux8: case Iop_MulHi16Ux4:
4010 case Iop_QNarrow32Sx2: case Iop_QNarrow16Sx4:
4011 case Iop_QNarrow16Ux4: case Iop_Add8x8: case Iop_Add32x2:
4012 case Iop_QAdd8Sx8: case Iop_QAdd16Sx4: case Iop_QAdd8Ux8:
4013 case Iop_QAdd16Ux4: case Iop_Add16x4: case Iop_CmpEQ8x8:
4014 case Iop_CmpEQ32x2: case Iop_CmpEQ16x4: case Iop_CmpGT8Sx8:
4015 case Iop_CmpGT32Sx2: case Iop_CmpGT16Sx4: case Iop_MulHi16Sx4:
4016 case Iop_Mul16x4: case Iop_ShlN32x2: case Iop_ShlN16x4:
4017 case Iop_SarN32x2: case Iop_SarN16x4: case Iop_ShrN32x2:
4018 case Iop_ShrN16x4: case Iop_Sub8x8: case Iop_Sub32x2:
4019 case Iop_QSub8Sx8: case Iop_QSub16Sx4: case Iop_QSub8Ux8:
4020 case Iop_QSub16Ux4: case Iop_Sub16x4: case Iop_InterleaveHI8x8:
4021 case Iop_InterleaveHI32x2: case Iop_InterleaveHI16x4:
4022 case Iop_InterleaveLO8x8: case Iop_InterleaveLO32x2:
4023 case Iop_InterleaveLO16x4: case Iop_SarN8x8:
4024 case Iop_Perm8x8: case Iop_ShlN8x8: case Iop_Mul32x2:
4025 case Iop_CatEvenLanes16x4: case Iop_CatOddLanes16x4:
4026 n64:
4027 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4028 break;
4029
4030 default:
4031 VG_(printf)("instrument_arithop(64-bit): unhandled: ");
4032 ppIROp(op);
4033 tl_assert(0);
4034 }
4035 }
4036}
4037
4038static
4039void gen_call_nonptr_or_unknown_range ( PCEnv* pce,
4040 IRAtom* addr, IRAtom* len )
4041{
4042 gen_dirty_v_WW( pce,
4043 &nonptr_or_unknown_range,
4044 "nonptr_or_unknown_range",
4045 addr, len );
4046}
4047
4048/* iii describes zero or more non-exact integer register updates. For
4049 each one, generate IR to get the containing register, apply
4050 nonptr_or_unknown to it, and write it back again. */
4051static void gen_nonptr_or_unknown_for_III( PCEnv* pce, IntRegInfo* iii )
4052{
4053 Int i;
4054 tl_assert(iii && iii->n_offsets >= 0);
4055 for (i = 0; i < iii->n_offsets; i++) {
4056 IRAtom* a1 = assignNew( 'I', pce, pce->gWordTy,
4057 IRExpr_Get( iii->offsets[i], pce->gWordTy ));
4058 IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4059 stmt( 'I', pce, IRStmt_Put( iii->offsets[i]
4060 + pce->guest_state_sizeB,
4061 mkexpr(a2) ));
4062 }
4063}
4064
4065/* Generate into 'ane', instrumentation for 'st'. Also copy 'st'
4066 itself into 'ane' (the caller does not do so). This is somewhat
4067 complex and relies heavily on the assumption that the incoming IR
4068 is in flat form.
4069
4070 Generally speaking, the instrumentation is placed after the
4071 original statement, so that results computed by the original can be
4072 used in the instrumentation. However, that isn't safe for memory
4073 references, since we need the instrumentation (hence bounds check
4074 and potential error message) to happen before the reference itself,
4075 as the latter could cause a fault. */
4076static void schemeS ( PCEnv* pce, IRStmt* st )
4077{
4078 tl_assert(st);
4079 tl_assert(isFlatIRStmt(st));
4080
4081 switch (st->tag) {
4082
4083 case Ist_Dirty: {
4084 Int i;
4085 IRDirty* di;
4086 stmt( 'C', pce, st );
4087 /* nasty. assumes that (1) all helpers are unconditional,
4088 and (2) all outputs are non-ptr */
4089 di = st->Ist.Dirty.details;
4090 /* deal with the return tmp, if any */
4091 if (di->tmp != IRTemp_INVALID
4092 && typeOfIRTemp(pce->bb->tyenv, di->tmp) == pce->gWordTy) {
4093 /* di->tmp is shadowed. Set it to NONPTR. */
4094 IRTemp dstv = newShadowTmp( pce, di->tmp );
4095 if (pce->gWordTy == Ity_I32) {
4096 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4097 } else {
4098 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4099 }
4100 }
4101 /* apply the nonptr_or_unknown technique to any parts of
4102 the guest state that happen to get written */
4103 for (i = 0; i < di->nFxState; i++) {
4104 IntRegInfo iii;
4105 tl_assert(di->fxState[i].fx != Ifx_None);
4106 if (di->fxState[i].fx == Ifx_Read)
4107 continue; /* this bit is only read -- not interesting */
4108 get_IntRegInfo( &iii, di->fxState[i].offset,
4109 di->fxState[i].size );
4110 tl_assert(iii.n_offsets >= -1
4111 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4112 /* Deal with 3 possible cases, same as with Ist_Put
4113 elsewhere in this function. */
4114 if (iii.n_offsets == -1) {
4115 /* case (1): exact write of an integer register. */
4116 IRAtom* a1
4117 = assignNew( 'I', pce, pce->gWordTy,
4118 IRExpr_Get( iii.offsets[i], pce->gWordTy ));
4119 IRTemp a2 = gen_call_nonptr_or_unknown_w( pce, a1 );
4120 stmt( 'I', pce, IRStmt_Put( iii.offsets[i]
4121 + pce->guest_state_sizeB,
4122 mkexpr(a2) ));
4123 } else {
4124 /* when == 0: case (3): no instrumentation needed */
4125 /* when > 0: case (2) .. complex case. Fish out the
4126 stored value for the whole register, heave it
4127 through nonptr_or_unknown, and use that as the new
4128 shadow value. */
4129 tl_assert(iii.n_offsets >= 0
4130 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4131 gen_nonptr_or_unknown_for_III( pce, &iii );
4132 }
4133 } /* for (i = 0; i < di->nFxState; i++) */
4134 /* finally, deal with memory outputs */
4135 if (di->mFx != Ifx_None) {
4136 tl_assert(di->mAddr && isIRAtom(di->mAddr));
4137 tl_assert(di->mSize > 0);
4138 gen_call_nonptr_or_unknown_range( pce, di->mAddr,
4139 mkIRExpr_HWord(di->mSize));
4140 }
4141 break;
4142 }
4143
4144 case Ist_NoOp:
4145 break;
4146
4147 /* nothing interesting in these; just copy them through */
4148 case Ist_AbiHint:
4149 case Ist_MBE:
4150 case Ist_Exit:
4151 case Ist_IMark:
4152 stmt( 'C', pce, st );
4153 break;
4154
4155 case Ist_PutI: {
4156 IRRegArray* descr = st->Ist.PutI.descr;
4157 stmt( 'C', pce, st );
4158 tl_assert(descr && descr->elemTy);
4159 if (is_integer_guest_reg_array(descr)) {
4160 /* if this fails, is_integer_guest_reg_array is returning
4161 bogus results */
4162 tl_assert(descr->elemTy == pce->gWordTy);
4163 stmt(
4164 'I', pce,
4165 IRStmt_PutI(
4166 mkIRRegArray(descr->base + pce->guest_state_sizeB,
4167 descr->elemTy, descr->nElems),
4168 st->Ist.PutI.ix,
4169 st->Ist.PutI.bias,
4170 schemeEw_Atom( pce, st->Ist.PutI.data)
4171 )
4172 );
4173 }
4174 break;
4175 }
4176
4177 case Ist_Put: {
4178 /* PUT(offset) = atom */
4179 /* 3 cases:
4180 1. It's a complete write of an integer register. Get hold of
4181 'atom's shadow value and write it in the shadow state.
4182 2. It's a partial write of an integer register. Let the write
4183 happen, then fish out the complete register value and see if,
4184 via range checking, consultation of tea leaves, etc, its
4185 shadow value can be upgraded to anything useful.
4186 3. It is none of the above. Generate no instrumentation. */
4187 IntRegInfo iii;
4188 IRType ty;
4189 stmt( 'C', pce, st );
4190 ty = typeOfIRExpr(pce->bb->tyenv, st->Ist.Put.data);
4191 get_IntRegInfo( &iii, st->Ist.Put.offset,
4192 sizeofIRType(ty) );
4193 if (iii.n_offsets == -1) {
4194 /* case (1): exact write of an integer register. */
4195 tl_assert(ty == pce->gWordTy);
4196 stmt( 'I', pce,
4197 IRStmt_Put( st->Ist.Put.offset
4198 + pce->guest_state_sizeB,
4199 schemeEw_Atom( pce, st->Ist.Put.data)) );
4200 } else {
4201 /* when == 0: case (3): no instrumentation needed */
4202 /* when > 0: case (2) .. complex case. Fish out the
4203 stored value for the whole register, heave it through
4204 nonptr_or_unknown, and use that as the new shadow
4205 value. */
4206 tl_assert(iii.n_offsets >= 0
4207 && iii.n_offsets <= N_INTREGINFO_OFFSETS);
4208 gen_nonptr_or_unknown_for_III( pce, &iii );
4209 }
4210 break;
4211 } /* case Ist_Put */
4212
4213 case Ist_Store: {
4214 /* We have: STle(addr) = data
4215 if data is int-word sized, do
4216 check_store4(addr, addr#, data, data#)
4217 for all other stores
4218 check_store{1,2}(addr, addr#, data)
4219
4220 The helper actually *does* the store, so that it can do
4221 the post-hoc ugly hack of inspecting and "improving" the
4222 shadow data after the store, in the case where it isn't an
4223 aligned word store.
4224 */
4225 IRExpr* data = st->Ist.Store.data;
4226 IRExpr* addr = st->Ist.Store.addr;
4227 IRType d_ty = typeOfIRExpr(pce->bb->tyenv, data);
4228 IRExpr* addrv = schemeEw_Atom( pce, addr );
4229 if (pce->gWordTy == Ity_I32) {
4230 /* ------ 32 bit host/guest (cough, cough) ------ */
4231 switch (d_ty) {
4232 /* Integer word case */
4233 case Ity_I32: {
4234 IRExpr* datav = schemeEw_Atom( pce, data );
4235 gen_dirty_v_WWWW( pce,
4236 &check_store4_P, "check_store4_P",
4237 addr, addrv, data, datav );
4238 break;
4239 }
4240 /* Integer subword cases */
4241 case Ity_I16:
4242 gen_dirty_v_WWW( pce,
4243 &check_store2, "check_store2",
4244 addr, addrv,
4245 uwiden_to_host_word( pce, data ));
4246 break;
4247 case Ity_I8:
4248 gen_dirty_v_WWW( pce,
4249 &check_store1, "check_store1",
4250 addr, addrv,
4251 uwiden_to_host_word( pce, data ));
4252 break;
4253 /* 64-bit float. Pass store data in 2 32-bit pieces. */
4254 case Ity_F64: {
4255 IRAtom* d64 = assignNew( 'I', pce, Ity_I64,
4256 unop(Iop_ReinterpF64asI64, data) );
4257 IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4258 unop(Iop_64to32, d64) );
4259 IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4260 unop(Iop_64HIto32, d64) );
4261 gen_dirty_v_WWWW( pce,
4262 &check_store8_ms4B_ls4B,
4263 "check_store8_ms4B_ls4B",
4264 addr, addrv, dHi32, dLo32 );
4265 break;
4266 }
4267 /* 32-bit float. We can just use _store4, but need
4268 to futz with the argument type. */
4269 case Ity_F32: {
4270 IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4271 unop(Iop_ReinterpF32asI32,
4272 data ) );
4273 gen_dirty_v_WWW( pce,
4274 &check_store4,
4275 "check_store4",
4276 addr, addrv, i32 );
4277 break;
4278 }
4279 /* 64-bit int. Pass store data in 2 32-bit pieces. */
4280 case Ity_I64: {
4281 IRAtom* dLo32 = assignNew( 'I', pce, Ity_I32,
4282 unop(Iop_64to32, data) );
4283 IRAtom* dHi32 = assignNew( 'I', pce, Ity_I32,
4284 unop(Iop_64HIto32, data) );
4285 gen_dirty_v_WWWW( pce,
4286 &check_store8_ms4B_ls4B,
4287 "check_store8_ms4B_ls4B",
4288 addr, addrv, dHi32, dLo32 );
4289 break;
4290 }
4291
4292 /* 128-bit vector. Pass store data in 4 32-bit pieces.
4293 This is all very ugly and inefficient, but it is
4294 hard to better without considerably complicating the
4295 store-handling schemes. */
4296 case Ity_V128: {
4297 IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4298 unop(Iop_V128HIto64, data) );
4299 IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4300 unop(Iop_V128to64, data) );
4301 IRAtom* w3 = assignNew( 'I', pce, Ity_I32,
4302 unop(Iop_64HIto32, dHi64) );
4303 IRAtom* w2 = assignNew( 'I', pce, Ity_I32,
4304 unop(Iop_64to32, dHi64) );
4305 IRAtom* w1 = assignNew( 'I', pce, Ity_I32,
4306 unop(Iop_64HIto32, dLo64) );
4307 IRAtom* w0 = assignNew( 'I', pce, Ity_I32,
4308 unop(Iop_64to32, dLo64) );
4309 gen_dirty_v_6W( pce,
4310 &check_store16_ms4B_4B_4B_ls4B,
4311 "check_store16_ms4B_4B_4B_ls4B",
4312 addr, addrv, w3, w2, w1, w0 );
4313 break;
4314 }
4315
4316
4317 default:
4318 ppIRType(d_ty); tl_assert(0);
4319 }
4320 } else {
4321 /* ------ 64 bit host/guest (cough, cough) ------ */
4322 switch (d_ty) {
4323 /* Integer word case */
4324 case Ity_I64: {
4325 IRExpr* datav = schemeEw_Atom( pce, data );
4326 gen_dirty_v_WWWW( pce,
4327 &check_store8_P, "check_store8_P",
4328 addr, addrv, data, datav );
4329 break;
4330 }
4331 /* Integer subword cases */
4332 case Ity_I32:
4333 gen_dirty_v_WWW( pce,
4334 &check_store4, "check_store4",
4335 addr, addrv,
4336 uwiden_to_host_word( pce, data ));
4337 break;
4338 case Ity_I16:
4339 gen_dirty_v_WWW( pce,
4340 &check_store2, "check_store2",
4341 addr, addrv,
4342 uwiden_to_host_word( pce, data ));
4343 break;
4344 case Ity_I8:
4345 gen_dirty_v_WWW( pce,
4346 &check_store1, "check_store1",
4347 addr, addrv,
4348 uwiden_to_host_word( pce, data ));
4349 break;
4350 /* 128-bit vector. Pass store data in 2 64-bit pieces. */
4351 case Ity_V128: {
4352 IRAtom* dHi64 = assignNew( 'I', pce, Ity_I64,
4353 unop(Iop_V128HIto64, data) );
4354 IRAtom* dLo64 = assignNew( 'I', pce, Ity_I64,
4355 unop(Iop_V128to64, data) );
4356 gen_dirty_v_WWWW( pce,
4357 &check_store16_ms8B_ls8B,
4358 "check_store16_ms8B_ls8B",
4359 addr, addrv, dHi64, dLo64 );
4360 break;
4361 }
4362 /* 64-bit float. */
4363 case Ity_F64: {
4364 IRAtom* dI = assignNew( 'I', pce, Ity_I64,
4365 unop(Iop_ReinterpF64asI64,
4366 data ) );
4367 gen_dirty_v_WWW( pce,
4368 &check_store8_all8B,
4369 "check_store8_all8B",
4370 addr, addrv, dI );
4371 break;
4372 }
4373 /* 32-bit float. We can just use _store4, but need
4374 to futz with the argument type. */
4375 case Ity_F32: {
4376 IRAtom* i32 = assignNew( 'I', pce, Ity_I32,
4377 unop(Iop_ReinterpF32asI32,
4378 data ) );
4379 IRAtom* i64 = assignNew( 'I', pce, Ity_I64,
4380 unop(Iop_32Uto64,
4381 i32 ) );
4382 gen_dirty_v_WWW( pce,
4383 &check_store4,
4384 "check_store4",
4385 addr, addrv, i64 );
4386 break;
4387 }
4388 default:
4389 ppIRType(d_ty); tl_assert(0);
4390 }
4391 }
4392 /* And don't copy the original, since the helper does the
4393 store. Ick. */
4394 break;
4395 } /* case Ist_Store */
4396
4397 case Ist_WrTmp: {
4398 /* This is the only place we have to deal with the full
4399 IRExpr range. In all other places where an IRExpr could
4400 appear, we in fact only get an atom (Iex_RdTmp or
4401 Iex_Const). */
4402 IRExpr* e = st->Ist.WrTmp.data;
4403 IRType e_ty = typeOfIRExpr( pce->bb->tyenv, e );
4404 Bool isWord = e_ty == pce->gWordTy;
4405 IRTemp dst = st->Ist.WrTmp.tmp;
4406 IRTemp dstv = isWord ? newShadowTmp( pce, dst )
4407 : IRTemp_INVALID;
4408
4409 switch (e->tag) {
4410
4411 case Iex_Const: {
4412 stmt( 'C', pce, st );
4413 if (isWord)
4414 assign( 'I', pce, dstv, schemeEw_Atom( pce, e ) );
4415 break;
4416 }
4417
4418 case Iex_CCall: {
4419 stmt( 'C', pce, st );
4420 if (isWord)
4421 assign( 'I', pce, dstv,
4422 mkexpr( gen_call_nonptr_or_unknown_w(
4423 pce, mkexpr(dst))));
4424 break;
4425 }
4426
4427 case Iex_Mux0X: {
4428 /* Just steer the shadow values in the same way as the
4429 originals. */
4430 stmt( 'C', pce, st );
4431 if (isWord)
4432 assign( 'I', pce, dstv,
4433 IRExpr_Mux0X(
4434 e->Iex.Mux0X.cond,
4435 schemeEw_Atom( pce, e->Iex.Mux0X.expr0 ),
4436 schemeEw_Atom( pce, e->Iex.Mux0X.exprX ) ));
4437 break;
4438 }
4439
4440 case Iex_RdTmp: {
4441 stmt( 'C', pce, st );
4442 if (isWord)
4443 assign( 'I', pce, dstv, schemeEw_Atom( pce, e ));
4444 break;
4445 }
4446
4447 case Iex_Load: {
4448 IRExpr* addr = e->Iex.Load.addr;
4449 HChar* h_nm = NULL;
4450 void* h_fn = NULL;
4451 IRExpr* addrv = NULL;
4452 if (pce->gWordTy == Ity_I32) {
4453 /* 32 bit host/guest (cough, cough) */
4454 switch (e_ty) {
4455 /* Ity_I32: helper returns shadow value. */
4456 case Ity_I32: h_fn = &check_load4_P;
4457 h_nm = "check_load4_P"; break;
4458 /* all others: helper does not return a shadow
4459 value. */
4460 case Ity_V128: h_fn = &check_load16;
4461 h_nm = "check_load16"; break;
4462 case Ity_I64:
4463 case Ity_F64: h_fn = &check_load8;
4464 h_nm = "check_load8"; break;
4465 case Ity_F32: h_fn = &check_load4;
4466 h_nm = "check_load4"; break;
4467 case Ity_I16: h_fn = &check_load2;
4468 h_nm = "check_load2"; break;
4469 case Ity_I8: h_fn = &check_load1;
4470 h_nm = "check_load1"; break;
4471 default: ppIRType(e_ty); tl_assert(0);
4472 }
4473 addrv = schemeEw_Atom( pce, addr );
4474 if (e_ty == Ity_I32) {
4475 assign( 'I', pce, dstv,
4476 mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4477 addr, addrv )) );
4478 } else {
4479 gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4480 }
4481 } else {
4482 /* 64 bit host/guest (cough, cough) */
4483 switch (e_ty) {
4484 /* Ity_I64: helper returns shadow value. */
4485 case Ity_I64: h_fn = &check_load8_P;
4486 h_nm = "check_load8_P"; break;
4487 /* all others: helper does not return a shadow
4488 value. */
4489 case Ity_V128: h_fn = &check_load16;
4490 h_nm = "check_load16"; break;
4491 case Ity_F64: h_fn = &check_load8;
4492 h_nm = "check_load8"; break;
4493 case Ity_F32:
4494 case Ity_I32: h_fn = &check_load4;
4495 h_nm = "check_load4"; break;
4496 case Ity_I16: h_fn = &check_load2;
4497 h_nm = "check_load2"; break;
4498 case Ity_I8: h_fn = &check_load1;
4499 h_nm = "check_load1"; break;
4500 default: ppIRType(e_ty); tl_assert(0);
4501 }
4502 addrv = schemeEw_Atom( pce, addr );
4503 if (e_ty == Ity_I64) {
4504 assign( 'I', pce, dstv,
4505 mkexpr( gen_dirty_W_WW( pce, h_fn, h_nm,
4506 addr, addrv )) );
4507 } else {
4508 gen_dirty_v_WW( pce, h_fn, h_nm, addr, addrv );
4509 }
4510 }
4511 /* copy the original -- must happen after the helper call */
4512 stmt( 'C', pce, st );
4513 break;
4514 }
4515
4516 case Iex_GetI: {
4517 IRRegArray* descr = e->Iex.GetI.descr;
4518 stmt( 'C', pce, st );
4519 tl_assert(descr && descr->elemTy);
4520 if (is_integer_guest_reg_array(descr)) {
4521 /* if this fails, is_integer_guest_reg_array is
4522 returning bogus results */
4523 tl_assert(isWord);
4524 assign(
4525 'I', pce, dstv,
4526 IRExpr_GetI(
4527 mkIRRegArray(descr->base + pce->guest_state_sizeB,
4528 descr->elemTy, descr->nElems),
4529 e->Iex.GetI.ix,
4530 e->Iex.GetI.bias
4531 )
4532 );
4533 }
4534 break;
4535 }
4536
4537 case Iex_Get: {
4538 stmt( 'C', pce, st );
4539 if (isWord) {
4540 /* guest-word-typed tmp assignment, so it will have a
4541 shadow tmp, and we must make an assignment to
4542 that */
4543 if (is_integer_guest_reg(e->Iex.Get.offset,
4544 sizeofIRType(e->Iex.Get.ty))) {
4545 assign( 'I', pce, dstv,
4546 IRExpr_Get( e->Iex.Get.offset
4547 + pce->guest_state_sizeB,
4548 e->Iex.Get.ty) );
4549 } else {
4550 if (pce->hWordTy == Ity_I32) {
4551 assign( 'I', pce, dstv, mkU32( (UWord)NONPTR ));
4552 } else {
4553 assign( 'I', pce, dstv, mkU64( (UWord)NONPTR ));
4554 }
4555 }
4556 } else {
4557 /* tmp isn't guest-word-typed, so isn't shadowed, so
4558 generate no instrumentation */
4559 }
4560 break;
4561 }
4562
4563 case Iex_Unop: {
4564 stmt( 'C', pce, st );
4565 tl_assert(isIRAtom(e->Iex.Unop.arg));
4566 if (isWord)
4567 instrument_arithop( pce, dst, dstv, e->Iex.Unop.op,
4568 e->Iex.Unop.arg,
4569 NULL, NULL, NULL );
4570 break;
4571 }
4572
4573 case Iex_Binop: {
4574 stmt( 'C', pce, st );
4575 tl_assert(isIRAtom(e->Iex.Binop.arg1));
4576 tl_assert(isIRAtom(e->Iex.Binop.arg2));
4577 if (isWord)
4578 instrument_arithop( pce, dst, dstv, e->Iex.Binop.op,
4579 e->Iex.Binop.arg1, e->Iex.Binop.arg2,
4580 NULL, NULL );
4581 break;
4582 }
4583
4584 case Iex_Triop: {
4585 stmt( 'C', pce, st );
4586 tl_assert(isIRAtom(e->Iex.Triop.arg1));
4587 tl_assert(isIRAtom(e->Iex.Triop.arg2));
4588 tl_assert(isIRAtom(e->Iex.Triop.arg3));
4589 if (isWord)
4590 instrument_arithop( pce, dst, dstv, e->Iex.Triop.op,
4591 e->Iex.Triop.arg1, e->Iex.Triop.arg2,
4592 e->Iex.Triop.arg3, NULL );
4593 break;
4594 }
4595
4596 case Iex_Qop: {
4597 stmt( 'C', pce, st );
4598 tl_assert(isIRAtom(e->Iex.Qop.arg1));
4599 tl_assert(isIRAtom(e->Iex.Qop.arg2));
4600 tl_assert(isIRAtom(e->Iex.Qop.arg3));
4601 tl_assert(isIRAtom(e->Iex.Qop.arg4));
4602 if (isWord)
4603 instrument_arithop( pce, dst, dstv, e->Iex.Qop.op,
4604 e->Iex.Qop.arg1, e->Iex.Qop.arg2,
4605 e->Iex.Qop.arg3, e->Iex.Qop.arg4 );
4606 break;
4607 }
4608
4609 default:
4610 goto unhandled;
4611 } /* switch (e->tag) */
4612
4613 break;
4614
4615 } /* case Ist_WrTmp */
4616
4617 default:
4618 unhandled:
4619 ppIRStmt(st);
4620 tl_assert(0);
4621 }
4622}
4623
4624
4625IRSB* h_instrument ( VgCallbackClosure* closure,
4626 IRSB* sbIn,
4627 VexGuestLayout* layout,
4628 VexGuestExtents* vge,
4629 IRType gWordTy, IRType hWordTy )
4630{
4631 Bool verboze = 0||False;
4632 Int i /*, j*/;
4633 PCEnv pce;
4634 struct _SGEnv* sgenv;
4635
4636 if (gWordTy != hWordTy) {
4637 /* We don't currently support this case. */
4638 VG_(tool_panic)("host/guest word size mismatch");
4639 }
4640
4641 /* Check we're not completely nuts */
4642 tl_assert(sizeof(UWord) == sizeof(void*));
4643 tl_assert(sizeof(Word) == sizeof(void*));
4644 tl_assert(sizeof(Addr) == sizeof(void*));
4645 tl_assert(sizeof(ULong) == 8);
4646 tl_assert(sizeof(Long) == 8);
4647 tl_assert(sizeof(Addr64) == 8);
4648 tl_assert(sizeof(UInt) == 4);
4649 tl_assert(sizeof(Int) == 4);
4650
4651 /* Set up the running environment. Only .bb is modified as we go
4652 along. */
4653 pce.bb = deepCopyIRSBExceptStmts(sbIn);
4654 pce.trace = verboze;
4655 pce.n_originalTmps = sbIn->tyenv->types_used;
4656 pce.hWordTy = hWordTy;
4657 pce.gWordTy = gWordTy;
4658 pce.guest_state_sizeB = layout->total_sizeB;
4659 pce.tmpMap = LibVEX_Alloc(pce.n_originalTmps * sizeof(IRTemp));
4660 for (i = 0; i < pce.n_originalTmps; i++)
4661 pce.tmpMap[i] = IRTemp_INVALID;
4662
4663 /* Also set up for the sg_ instrumenter. See comments
4664 at the top of this instrumentation section for details. */
4665 sgenv = sg_instrument_init();
4666
4667 /* Stay sane. These two should agree! */
4668 tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE);
4669
4670 /* Copy verbatim any IR preamble preceding the first IMark */
4671
4672 i = 0;
4673 while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
4674 IRStmt* st = sbIn->stmts[i];
4675 tl_assert(st);
4676 tl_assert(isFlatIRStmt(st));
4677 stmt( 'C', &pce, sbIn->stmts[i] );
4678 i++;
4679 }
4680
4681 /* Nasty problem. IR optimisation of the pre-instrumented IR may
4682 cause the IR following the preamble to contain references to IR
4683 temporaries defined in the preamble. Because the preamble isn't
4684 instrumented, these temporaries don't have any shadows.
4685 Nevertheless uses of them following the preamble will cause
4686 memcheck to generate references to their shadows. End effect is
4687 to cause IR sanity check failures, due to references to
4688 non-existent shadows. This is only evident for the complex
4689 preambles used for function wrapping on TOC-afflicted platforms
4690 (ppc64-linux, ppc32-aix5, ppc64-aix5).
4691
4692 The following loop therefore scans the preamble looking for
4693 assignments to temporaries. For each one found it creates an
4694 assignment to the corresponding shadow temp, marking it as
4695 'defined'. This is the same resulting IR as if the main
4696 instrumentation loop before had been applied to the statement
4697 'tmp = CONSTANT'.
4698 */
4699#if 0
4700 // FIXME: this isn't exactly right; only needs to generate shadows
4701 // for guest-word-typed temps
4702 for (j = 0; j < i; j++) {
4703 if (sbIn->stmts[j]->tag == Ist_WrTmp) {
4704 /* findShadowTmpV checks its arg is an original tmp;
4705 no need to assert that here. */
4706 IRTemp tmp_o = sbIn->stmts[j]->Ist.WrTmp.tmp;
4707 IRTemp tmp_s = findShadowTmp(&pce, tmp_o);
4708 IRType ty_s = typeOfIRTemp(sbIn->tyenv, tmp_s);
4709 assign( 'V', &pce, tmp_s, definedOfType( ty_s ) );
4710 if (0) {
4711 VG_(printf)("create shadow tmp for preamble tmp [%d] ty ", j);
4712 ppIRType( ty_s );
4713 VG_(printf)("\n");
4714 }
4715 }
4716 }
4717#endif
4718
4719 /* Iterate over the remaining stmts to generate instrumentation. */
4720
4721 tl_assert(sbIn->stmts_used > 0);
4722 tl_assert(i >= 0);
4723 tl_assert(i < sbIn->stmts_used);
4724 tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
4725
4726 for (/*use current i*/; i < sbIn->stmts_used; i++) {
4727 /* generate sg_ instrumentation for this stmt */
4728 sg_instrument_IRStmt( sgenv, pce.bb, sbIn->stmts[i],
4729 layout, gWordTy, hWordTy );
4730 /* generate h_ instrumentation for this stmt */
4731 schemeS( &pce, sbIn->stmts[i] );
4732 }
4733
4734 /* generate sg_ instrumentation for the final jump */
4735 sg_instrument_final_jump( sgenv, pce.bb, sbIn->next, sbIn->jumpkind,
4736 layout, gWordTy, hWordTy );
4737
4738 /* and finalise .. */
4739 sg_instrument_fini( sgenv );
4740
4741 return pce.bb;
4742}
4743
4744
4745/*--------------------------------------------------------------------*/
4746/*--- Initialisation ---*/
4747/*--------------------------------------------------------------------*/
4748
4749void h_pre_clo_init ( void )
4750{
4751 // Other initialisation
4752 init_shadow_memory();
4753 init_lossage();
4754}
4755
4756void h_post_clo_init ( void )
4757{
4758}
4759
4760/*--------------------------------------------------------------------*/
4761/*--- Finalisation ---*/
4762/*--------------------------------------------------------------------*/
4763
4764void h_fini ( Int exitcode )
4765{
4766 if (VG_(clo_verbosity) >= 2) {
4767 VG_(message)(Vg_DebugMsg,
4768 " h_: %'10llu client allocs, %'10llu client frees",
4769 stats__client_mallocs, stats__client_frees);
4770 VG_(message)(Vg_DebugMsg,
4771 " h_: %'10llu Segs allocd, %'10llu Segs recycled",
4772 stats__segs_allocd, stats__segs_recycled);
sewardj024598e2008-09-18 14:43:05 +00004773 }
4774
sewardj4815eb52008-10-20 23:33:49 +00004775#if 0
sewardj024598e2008-09-18 14:43:05 +00004776 if (h_clo_lossage_check) {
4777 VG_(message)(Vg_UserMsg, "");
4778 VG_(message)(Vg_UserMsg, "%12lld total memory references",
4779 stats__tot_mem_refs);
4780 VG_(message)(Vg_UserMsg, "%12lld of which are in a known segment",
4781 stats__refs_in_a_seg);
4782 VG_(message)(Vg_UserMsg, "%12lld of which are 'lost' w.r.t the seg",
4783 stats__refs_lost_seg);
4784 VG_(message)(Vg_UserMsg, "");
4785 show_lossage();
4786 VG_(message)(Vg_UserMsg, "");
4787 } else {
4788 tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
4789 }
sewardj4815eb52008-10-20 23:33:49 +00004790#endif
sewardj024598e2008-09-18 14:43:05 +00004791}
4792
4793
4794/*--------------------------------------------------------------------*/
4795/*--- end h_main.c ---*/
4796/*--------------------------------------------------------------------*/