1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Ptrcheck: a pointer-use checker.                             ---*/
4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- This file checks heap accesses.                              ---*/
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---                                                     h_main.c ---*/
6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This file is part of Ptrcheck, a Valgrind tool for checking pointer
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   use in programs.
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Initial version (Annelid):
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2003-2013 Nicholas Nethercote
15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      njn@valgrind.org
16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Valgrind-3.X port:
18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2008-2013 OpenWorks Ltd
20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      info@open-works.co.uk
21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This program is free software; you can redistribute it and/or
23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   modify it under the terms of the GNU General Public License as
24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   published by the Free Software Foundation; either version 2 of the
25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   License, or (at your option) any later version.
26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   This program is distributed in the hope that it will be useful, but
28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   WITHOUT ANY WARRANTY; without even the implied warranty of
29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   General Public License for more details.
31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   You should have received a copy of the GNU General Public License
33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   along with this program; if not, write to the Free Software
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   02111-1307, USA.
36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   The GNU General Public License is contained in the file COPYING.
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_basics.h"
41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_libcbase.h"
42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_libcprint.h"
43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_libcassert.h"
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_mallocfree.h"
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_execontext.h"
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_hashtable.h"
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_tooliface.h"
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_replacemalloc.h"
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_options.h"
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_execontext.h"
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_aspacemgr.h"    // VG_(am_shadow_malloc)
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_vki.h"          // VKI_MAX_PAGE_SIZE
53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_machine.h"      // VG_({get,set}_shadow_regs_area) et al
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_debuginfo.h"    // VG_(get_fnname)
55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_threadstate.h"  // VG_(get_running_tid)
56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_oset.h"
57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_vkiscnums.h"
58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_machine.h"
59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_wordfm.h"
60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_xarray.h"
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pc_common.h"
63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//#include "h_list.h"
65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "h_main.h"
66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "sg_main.h"   // sg_instrument_*, and struct _SGEnv
68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Debug/trace options                                  ---*/
73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ULong stats__client_mallocs = 0;
76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ULong stats__client_frees   = 0;
77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ULong stats__segs_allocd    = 0;
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ULong stats__segs_recycled  = 0;
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////////////////////////////////////////////////////
82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//                                                          //
83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Segments low level storage                               //
84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//                                                          //
85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////////////////////////////////////////////////////
86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// pc_common.c needs to see them, for error processing
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// we only start recycling segs when this many exist
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define N_FREED_SEGS (1 * 1000 * 1000)
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstruct _Seg {
94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Addr  addr;
95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SizeT szB; /* may be zero */
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ExeContext* ec;  /* where malloc'd or freed */
97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* When 1, indicates block is in use.  Otherwise, used to form a
98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      linked list of freed blocks, running from oldest freed block to
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      the most recently freed block. */
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct _Seg* nextfree;
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov};
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Determines if 'a' is before, within, or after seg's range.  Sets 'cmp' to
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// -1/0/1 accordingly.  Sets 'n' to the number of bytes before/within/after.
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n)
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (a < seg->addr) {
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *cmp = -1;
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *n   = seg->addr - a;
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else if (a < seg->addr + seg->szB && seg->szB > 0) {
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *cmp = 0;
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *n = a - seg->addr;
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *cmp = 1;
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      *n = a - (seg->addr + seg->szB);
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*inline*/ Bool Seg__is_freed(Seg* seg)
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!is_known_segment(seg))
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return seg->nextfree != (Seg*)1;
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovExeContext* Seg__where(Seg* seg)
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(is_known_segment(seg));
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return seg->ec;
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovSizeT Seg__size(Seg* seg)
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(is_known_segment(seg));
136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return seg->szB;
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovAddr Seg__addr(Seg* seg)
140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(is_known_segment(seg));
142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return seg->addr;
143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define N_SEGS_PER_GROUP 10000
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct _SegGroup {
150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      struct _SegGroup* admin;
151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */
152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Seg segs[N_SEGS_PER_GROUP];
153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SegGroup;
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic SegGroup* group_list = NULL;
157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UWord     nFreeSegs = 0;
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Seg*      freesegs_youngest = NULL;
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Seg*      freesegs_oldest = NULL;
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic SegGroup* new_SegGroup ( void ) {
163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup));
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(memset)(g, 0, sizeof(*g));
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return g;
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Get a completely new Seg */
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Seg* new_Seg ( void )
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Seg*      teg;
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   SegGroup* g;
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (group_list == NULL) {
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      g = new_SegGroup();
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      g->admin = NULL;
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      group_list = g;
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP);
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (group_list->nextfree == N_SEGS_PER_GROUP) {
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      g = new_SegGroup();
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      g->admin = group_list;
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      group_list = g;
183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(group_list->nextfree < N_SEGS_PER_GROUP);
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   teg = &group_list->segs[ group_list->nextfree ];
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   group_list->nextfree++;
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stats__segs_allocd++;
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return teg;
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Seg* get_Seg_for_malloc ( void )
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Seg* seg;
194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (nFreeSegs < N_FREED_SEGS) {
195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      seg = new_Seg();
196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      seg->nextfree = (Seg*)1;
197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return seg;
198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* else recycle the oldest Seg in the free list */
200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(freesegs_youngest);
201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(freesegs_oldest);
202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(freesegs_youngest != freesegs_oldest);
203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg = freesegs_oldest;
204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   freesegs_oldest = seg->nextfree;
205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   nFreeSegs--;
206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg->nextfree = (Seg*)1;
207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stats__segs_recycled++;
208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return seg;
209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void set_Seg_freed ( Seg* seg )
212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(seg);
214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(!Seg__is_freed(seg));
215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (nFreeSegs == 0) {
216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(freesegs_oldest == NULL);
217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(freesegs_youngest == NULL);
218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      seg->nextfree = NULL;
219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      freesegs_youngest = seg;
220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      freesegs_oldest = seg;
221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nFreeSegs++;
222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(freesegs_youngest);
224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(freesegs_oldest);
225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (nFreeSegs == 1) {
226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         tl_assert(freesegs_youngest == freesegs_oldest);
227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         tl_assert(freesegs_youngest != freesegs_oldest);
229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(freesegs_youngest->nextfree == NULL);
231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(seg != freesegs_youngest && seg != freesegs_oldest);
232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      seg->nextfree = NULL;
233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      freesegs_youngest->nextfree = seg;
234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      freesegs_youngest = seg;
235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nFreeSegs++;
236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic WordFM* addr_to_seg_map = NULL; /* GuestAddr -> Seg* */
240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void addr_to_seg_map_ENSURE_INIT ( void )
242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (UNLIKELY(addr_to_seg_map == NULL)) {
244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1",
245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    VG_(free), NULL/*unboxedcmp*/ );
246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Seg* find_Seg_by_addr ( Addr ga )
250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord keyW, valW;
252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   addr_to_seg_map_ENSURE_INIT();
253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) {
254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(keyW == ga);
255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return (Seg*)valW;
256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return NULL;
258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void bind_addr_to_Seg ( Addr ga, Seg* seg )
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool b;
264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   addr_to_seg_map_ENSURE_INIT();
265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   b = VG_(addToFM)( addr_to_seg_map, (UWord)ga, (UWord)seg );
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(!b); /* else ga is already bound */
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void unbind_addr_from_Seg ( Addr ga )
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool b;
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UWord keyW, valW;
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   addr_to_seg_map_ENSURE_INIT();
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   b = VG_(delFromFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga );
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(b); /* else ga was not already bound */
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(keyW == ga);
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(valW != 0);
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////////////////////////////////////////////////////
282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////////////////////////////////////////////////////
283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//////////////////////////////////////////////////////////////
284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Returns the added heap segment
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size )
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Seg* seg = get_Seg_for_malloc();
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg->addr = p;
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg->szB  = size;
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg->ec   = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(!Seg__is_freed(seg));
294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bind_addr_to_Seg(p, seg);
296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return seg;
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* alloc_and_new_mem_heap ( ThreadId tid,
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               SizeT size, SizeT alignment, Bool is_zeroed )
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Addr p;
307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ( ((SSizeT)size) < 0) return NULL;
309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   p = (Addr)VG_(cli_malloc)(alignment, size);
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (is_zeroed) VG_(memset)((void*)p, 0, size);
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   add_new_segment( tid, p, size );
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stats__client_mallocs++;
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return (void*)p;
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void die_and_free_mem_heap ( ThreadId tid, Seg* seg )
320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // Empty and free the actual block
322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(!Seg__is_freed(seg));
323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(cli_free)( (void*)seg->addr );
325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // Remember where freed
327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   set_Seg_freed(seg);
330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   unbind_addr_from_Seg( seg->addr );
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stats__client_frees++;
333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void handle_free_heap( ThreadId tid, void* p )
336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Seg* seg = find_Seg_by_addr( (Addr)p );
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!seg) {
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* freeing a block that wasn't malloc'd.  Ignore. */
340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return;
341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   die_and_free_mem_heap( tid, seg );
343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- malloc() et al replacements                          ---*/
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* h_replace_malloc ( ThreadId tid, SizeT n )
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        /*is_zeroed*/False );
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* h_replace___builtin_new ( ThreadId tid, SizeT n )
357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           /*is_zeroed*/False );
360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           /*is_zeroed*/False );
366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return alloc_and_new_mem_heap ( tid, n, align,
371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        /*is_zeroed*/False );
372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        /*is_zeroed*/True );
378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid h_replace_free ( ThreadId tid, void* p )
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // Should arguably check here if p.vseg matches the segID of the
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // pointed-to block... unfortunately, by this stage, we don't know what
384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // p.vseg is, because we don't know the address of p (the p here is a
385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // copy, and we've lost the address of its source).  To do so would
386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // require passing &p in, which would require rewriting part of
387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // vg_replace_malloc.c... argh.
388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //
389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // However, Memcheck does free checking, and will catch almost all
390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // violations this checking would have caught.  (Would only miss if we
391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // unluckily passed an unrelated pointer to the very start of a heap
392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // block that was unrelated to that block.  This is very unlikely!)    So
393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // we haven't lost much.
394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   handle_free_heap(tid, p);
396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid h_replace___builtin_delete ( ThreadId tid, void* p )
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   handle_free_heap(tid, p);
401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid h_replace___builtin_vec_delete ( ThreadId tid, void* p )
404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   handle_free_heap(tid, p);
406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Seg* seg;
411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* First try and find the block. */
413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   seg = find_Seg_by_addr( (Addr)p_old );
414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!seg)
415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return NULL;
416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(seg->addr == (Addr)p_old);
418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (new_size <= seg->szB) {
420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* new size is smaller: allocate, copy from old to new */
421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(memcpy)((void*)p_new, p_old, new_size);
423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Free old memory */
425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      die_and_free_mem_heap( tid, seg );
426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* This has to be after die_and_free_mem_heap, otherwise the
428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         former succeeds in shorting out the new block, not the
429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         old, in the case when both are on the same list.  */
430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      add_new_segment ( tid, p_new, new_size );
431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return (void*)p_new;
433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* new size is bigger: allocate, copy from old to new */
435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size);
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(memcpy)((void*)p_new, p_old, seg->szB);
437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Free old memory */
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      die_and_free_mem_heap( tid, seg );
440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* This has to be after die_and_free_mem_heap, otherwise the
442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         former succeeds in shorting out the new block, not the old,
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         in the case when both are on the same list.  NB jrs
444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         2008-Sept-11: not sure if this comment is valid/correct any
445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         more -- I suspect not. */
446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      add_new_segment ( tid, p_new, new_size );
447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return (void*)p_new;
449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovSizeT h_replace_malloc_usable_size ( ThreadId tid, void* p )
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Seg* seg = find_Seg_by_addr( (Addr)p );
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // There may be slop, but pretend there isn't because only the asked-for
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // area will have been shadowed properly.
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return ( seg ? seg->szB : 0 );
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Instrumentation                                              ---*/
464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The h_ instrumenter that follows is complex, since it deals with
467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   shadow value computation.
468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   It also needs to generate instrumentation for the sg_ side of
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   things.  That's relatively straightforward.  However, rather than
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   confuse the code herein any further, we simply delegate the problem
472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to sg_main.c, by using the four functions
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sg_instrument_{init,fini,IRStmt,final_jump}.  These four completely
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   abstractify the sg_ instrumentation.  See comments in sg_main.c's
475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   instrumentation section for further details. */
476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Carries info about a particular tmp.  The tmp's number is not
479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   recorded, as this is implied by (equal to) its index in the tmpMap
480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   in PCEnv.  The tmp's type is also not recorded, as this is present
481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   in PCEnv.sb->tyenv.
482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   When .kind is NonShad, .shadow may give the identity of the temp
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   currently holding the associated shadow value, or it may be
485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp_INVALID if code to compute the shadow has not yet been
486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   emitted.
487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   When .kind is Shad tmp holds a shadow value, and so .shadow must be
489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp_INVALID, since it is illogical for a shadow tmp itself to be
490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   shadowed.
491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   enum { NonShad=1, Shad=2 }
494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TempKind;
495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct {
498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      TempKind kind;
499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp   shadow;
500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TempMapEnt;
502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Carries around state during Ptrcheck instrumentation. */
506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef
507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct {
508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* MODIFIED: the superblock being constructed.  IRStmts are
509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         added. */
510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRSB* sb;
511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Bool  trace;
512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         current kind and possibly shadow temps for each temp in the
515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRSB being constructed.  Note that it does not contain the
516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         type of each tmp.  If you want to know the type, look at the
517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         relevant entry in sb->tyenv.  It follows that at all times
518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         during the instrumentation process, the valid indices for
519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         total number of NonShad and Shad temps allocated so far.
521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         The reason for this strange split (types in one place, all
523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         other info in another) is that we need the types to be
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         attached to sb so as to make it possible to do
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         instrumentation process.
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Note that only integer temps of the guest word size are
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         shadowed, since it is impossible (or meaningless) to hold a
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         pointer in any other type of temp. */
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      XArray* /* of TempMapEnt */ qmpMap;
532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* READONLY: the host word type.  Needed for constructing
534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         arguments of type 'HWord' to be passed to helper functions.
535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Ity_I32 or Ity_I64 only. */
536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRType hWordTy;
537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */
539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRType gWordTy;
540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* READONLY: the guest state size, so we can generate shadow
542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         offsets correctly. */
543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Int guest_state_sizeB;
544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PCEnv;
546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   demand), as they are encountered.  This is for two reasons.
549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (1) (less important reason): Many original tmps are unused due to
551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   initial IR optimisation, and we do not want to spaces in tables
552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tracking them.
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Shadow IRTemps are therefore allocated on demand.  pce.tmpMap is a
555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   table indexed [0 .. n_types-1], which gives the current shadow for
556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   each original tmp, or INVALID_IRTEMP if none is so far assigned.
557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   It is necessary to support making multiple assignments to a shadow
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   -- specifically, after testing a shadow for definedness, it needs
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to be made defined.  But IR's SSA property disallows this.
560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (2) (more important reason): Therefore, when a shadow needs to get
562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   a new value, a new temporary is created, the value is assigned to
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   that, and the tmpMap is updated to reflect the new binding.
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   A corollary is that if the tmpMap maps a given tmp to
566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   there's a read-before-write error in the original tmps.  The IR
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sanity checker should catch all such anomalies, however.
569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   both the table in pce->sb and to our auxiliary mapping.  Note that
573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   newTemp may cause pce->tmpMap to resize, hence previous results
574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   from VG_(indexXA)(pce->tmpMap) are invalidated. */
575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind )
576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Word       newIx;
578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   TempMapEnt ent;
579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp     tmp = newIRTemp(pce->sb->tyenv, ty);
580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ent.kind   = kind;
581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ent.shadow = IRTemp_INVALID;
582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   newIx = VG_(addToXA)( pce->qmpMap, &ent );
583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(newIx == (Word)tmp);
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return tmp;
585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Constructing IR fragments                            ---*/
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* add stmt to a bb */
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic /*inline*/ void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) {
593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (pce->trace) {
594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf)("  %c: ", cat);
595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ppIRStmt(st);
596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf)("\n");
597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   addStmtToIRSB(pce->sb, st);
599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque )
602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PCEnv* pce = (PCEnv*)opaque;
604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return newTemp( pce, ty, NonShad );
605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRSB* h_instrument ( VgCallbackClosure* closure,
609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     IRSB* sbIn,
610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VexGuestLayout* layout,
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     VexGuestExtents* vge,
612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     VexArchInfo* archinfo_host,
613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     IRType gWordTy, IRType hWordTy )
614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool  verboze = 0||False;
616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int   i /*, j*/;
617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PCEnv pce;
618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   struct _SGEnv* sgenv;
619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (gWordTy != hWordTy) {
621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* We don't currently support this case. */
622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(tool_panic)("host/guest word size mismatch");
623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Check we're not completely nuts */
626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(UWord)  == sizeof(void*));
627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(Word)   == sizeof(void*));
628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(Addr)   == sizeof(void*));
629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(ULong)  == 8);
630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(Long)   == 8);
631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(Addr64) == 8);
632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(UInt)   == 4);
633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sizeof(Int)    == 4);
634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Set up the running environment.  Both .sb and .tmpMap are
636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      modified as we go along.  Note that tmps are added to both
637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      .sb->tyenv and .tmpMap together, so the valid index-set for
638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      those two arrays should always be identical. */
639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(memset)(&pce, 0, sizeof(pce));
640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pce.sb                = deepCopyIRSBExceptStmts(sbIn);
641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pce.trace             = verboze;
642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pce.hWordTy           = hWordTy;
643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pce.gWordTy           = gWordTy;
644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pce.guest_state_sizeB = layout->total_sizeB;
645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pce.qmpMap = VG_(newXA)( VG_(malloc), "pc.h_instrument.1", VG_(free),
647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            sizeof(TempMapEnt));
648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < sbIn->tyenv->types_used; i++) {
649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      TempMapEnt ent;
650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ent.kind   = NonShad;
651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ent.shadow = IRTemp_INVALID;
652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(addToXA)( pce.qmpMap, &ent );
653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert( VG_(sizeXA)( pce.qmpMap ) == sbIn->tyenv->types_used );
655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Also set up for the sg_ instrumenter.  See comments at the top
657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      of this instrumentation section for details.  The two parameters
658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      constitute a closure, which sg_ can use to correctly generate
659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      new IRTemps as needed. */
660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sgenv = sg_instrument_init( for_sg__newIRTemp_cb,
661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               (void*)&pce );
662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Copy verbatim any IR preamble preceding the first IMark */
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   i = 0;
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRStmt* st = sbIn->stmts[i];
668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(st);
669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(isFlatIRStmt(st));
670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      stmt( 'C', &pce, sbIn->stmts[i] );
671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      i++;
672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Iterate over the remaining stmts to generate instrumentation. */
675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sbIn->stmts_used > 0);
677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(i >= 0);
678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(i < sbIn->stmts_used);
679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (/*use current i*/; i < sbIn->stmts_used; i++) {
682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* generate sg_ instrumentation for this stmt */
683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      sg_instrument_IRStmt( sgenv, pce.sb, sbIn->stmts[i],
684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            layout, gWordTy, hWordTy );
685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      stmt( 'C', &pce, sbIn->stmts[i] );
687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* generate sg_ instrumentation for the final jump */
690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sg_instrument_final_jump( sgenv, pce.sb, sbIn->next, sbIn->jumpkind,
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             layout, gWordTy, hWordTy );
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* and finalise .. */
694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sg_instrument_fini( sgenv );
695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* If this fails, there's been some serious snafu with tmp management,
697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      that should be investigated. */
698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert( VG_(sizeXA)( pce.qmpMap ) == pce.sb->tyenv->types_used );
699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(deleteXA)( pce.qmpMap );
700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return pce.sb;
702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Finalisation                                                 ---*/
707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid h_fini ( Int exitcode )
710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(message)(Vg_UserMsg,
713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   "For counts of detected and suppressed errors, "
714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   "rerun with: -v\n");
715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(clo_stats)) {
718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(message)(Vg_DebugMsg,
719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   "  h_:  %'10llu client allocs, %'10llu client frees\n",
720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   stats__client_mallocs, stats__client_frees);
721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(message)(Vg_DebugMsg,
722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled\n",
723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   stats__segs_allocd, stats__segs_recycled);
724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- end                                                 h_main.c ---*/
730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--------------------------------------------------------------------*/
731