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