1
2 /*--------------------------------------------------------------------*/
3 /*--- Replacements for malloc() et al, which run on the simulated ---*/
4 /*--- CPU. vg_replace_malloc.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2000-2013 Julian Seward
12 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30 */
31
32 /* ---------------------------------------------------------------------
33 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
34
35 These functions are drop-in replacements for malloc() and friends.
36 They have global scope, but are not intended to be called directly.
37 See pub_core_redir.h for the gory details.
38
39 This file can be linked into the vg_preload_<tool>.so file for any tool
40 that wishes to know about calls to malloc(). The tool must define all
41 the functions that will be called via 'info'.
42
43 It is called vg_replace_malloc.c because this filename appears in stack
44 traces, so we want the name to be (hopefully!) meaningful to users.
45
46 IMPORTANT: this file must not contain any floating point code, nor
47 any integer division. This is because on ARM these can cause calls
48 to helper functions, which will be unresolved within this .so.
49 Although it is usually the case that the client's ld.so instance
50 can bind them at runtime to the relevant functions in the client
51 executable, there is no guarantee of this; and so the client may
52 die via a runtime link failure. Hence the only safe approach is to
53 avoid such function calls in the first place. See "#define CALLOC"
54 below for a specific example.
55
56 A useful command is
57 for f in `find . -name "*preload*.so*"` ; \
58 do nm -A $f | grep " U " ; \
59 done
60
61 to see all the undefined symbols in all the preload shared objects.
62 ------------------------------------------------------------------ */
63
64 #include "pub_core_basics.h"
65 #include "pub_core_vki.h" // VKI_EINVAL, VKI_ENOMEM
66 #include "pub_core_clreq.h" // for VALGRIND_INTERNAL_PRINTF,
67 // VALGRIND_NON_SIMD_CALL[12]
68 #include "pub_core_debuginfo.h" // needed for pub_core_redir.h :(
69 #include "pub_core_mallocfree.h" // for VG_MIN_MALLOC_SZB, VG_AR_CLIENT
70 #include "pub_core_redir.h" // for VG_REPLACE_FUNCTION_*
71 #include "pub_core_replacemalloc.h"
72
73 /* Assignment of behavioural equivalence class tags: 1NNNP is intended
74 to be reserved for the Valgrind core. Current usage:
75
76 10010 ALLOC_or_NULL
77 10020 ZONEALLOC_or_NULL
78 10030 ALLOC_or_BOMB
79 10040 ZONEFREE
80 10050 FREE
81 10060 ZONECALLOC
82 10070 CALLOC
83 10080 ZONEREALLOC
84 10090 REALLOC
85 10100 ZONEMEMALIGN
86 10110 MEMALIGN
87 10120 VALLOC
88 10130 ZONEVALLOC
89 10140 MALLOPT
90 10150 MALLOC_TRIM
91 10160 POSIX_MEMALIGN
92 10170 MALLOC_USABLE_SIZE
93 10180 PANIC
94 10190 MALLOC_STATS
95 10200 MALLINFO
96 10210 DEFAULT_ZONE
97 10220 ZONE_CHECK
98 */
99
100 /* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style
101 mangling, could be supported properly by the redirects in this
102 module. Except we can't because it doesn't put its allocation
103 functions in libpgc.so but instead hardwires them into the
104 compilation unit holding main(), which makes them impossible to
105 intercept directly. Fortunately those fns seem to route everything
106 through to malloc/free.
107
108 mid-06: could be improved, since we can now intercept in the main
109 executable too.
110 */
111
112
113
114 /* Call here to exit if we can't continue. On Android we can't call
115 _exit for some reason, so we have to blunt-instrument it. */
116 __attribute__ ((__noreturn__))
my_exit(int x)117 static inline void my_exit ( int x )
118 {
119 # if defined(VGPV_arm_linux_android) || defined(VGPV_mips32_linux_android)
120 __asm__ __volatile__(".word 0xFFFFFFFF");
121 while (1) {}
122 # elif defined(VGPV_x86_linux_android)
123 __asm__ __volatile__("ud2");
124 while (1) {}
125 # else
126 extern __attribute__ ((__noreturn__)) void _exit(int status);
127 _exit(x);
128 # endif
129 }
130
131 /* Same problem with getpagesize. */
my_getpagesize(void)132 static inline int my_getpagesize ( void )
133 {
134 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
135 || defined(VGPV_mips32_linux_android)
136 return 4096; /* kludge - link failure on Android, for some reason */
137 # else
138 extern int getpagesize (void);
139 return getpagesize();
140 # endif
141 }
142
143
144 /* Compute the high word of the double-length unsigned product of U
145 and V. This is for calloc argument overflow checking; see comments
146 below. Algorithm as described in Hacker's Delight, chapter 8. */
umulHW(UWord u,UWord v)147 static UWord umulHW ( UWord u, UWord v )
148 {
149 UWord u0, v0, w0, rHi;
150 UWord u1, v1, w1,w2,t;
151 UWord halfMask = sizeof(UWord)==4 ? (UWord)0xFFFF
152 : (UWord)0xFFFFFFFFULL;
153 UWord halfShift = sizeof(UWord)==4 ? 16 : 32;
154 u0 = u & halfMask;
155 u1 = u >> halfShift;
156 v0 = v & halfMask;
157 v1 = v >> halfShift;
158 w0 = u0 * v0;
159 t = u1 * v0 + (w0 >> halfShift);
160 w1 = t & halfMask;
161 w2 = t >> halfShift;
162 w1 = u0 * v1 + w1;
163 rHi = u1 * v1 + w2 + (w1 >> halfShift);
164 return rHi;
165 }
166
167
168 /*------------------------------------------------------------*/
169 /*--- Replacing malloc() et al ---*/
170 /*------------------------------------------------------------*/
171
172 /* This struct is initially empty. Before the first use of any of
173 these functions, we make a client request which fills in the
174 fields.
175 */
176 static struct vg_mallocfunc_info info;
177 static int init_done;
178 #define DO_INIT if (UNLIKELY(!init_done)) init()
179
180 /* Startup hook - called as init section */
181 __attribute__((constructor))
182 static void init(void);
183
184 #define MALLOC_TRACE(format, args...) \
185 if (info.clo_trace_malloc) { \
186 VALGRIND_INTERNAL_PRINTF(format, ## args ); }
187
188 /* Below are new versions of malloc, __builtin_new, free,
189 __builtin_delete, calloc, realloc, memalign, and friends.
190
191 None of these functions are called directly - they are not meant to
192 be found by the dynamic linker. But ALL client calls to malloc()
193 and friends wind up here eventually. They get called because
194 vg_replace_malloc installs a bunch of code redirects which causes
195 Valgrind to use these functions rather than the ones they're
196 replacing.
197 */
198
199 /* The replacement functions are running on the simulated CPU.
200 The code on the simulated CPU does not necessarily use
201 all arguments. E.g. args can be ignored and/or only given
202 to a NON SIMD call.
203 The definedness of such 'unused' arguments will not be verified
204 by memcheck.
205 A call to 'trigger_memcheck_error_if_undefined' allows
206 memcheck to detect such errors for the otherwise unused args.
207 Apart of allowing memcheck to detect an error, the function
208 trigger_memcheck_error_if_undefined has no effect and
209 has a minimal cost for other tools replacing malloc functions.
210 */
trigger_memcheck_error_if_undefined(ULong x)211 static inline void trigger_memcheck_error_if_undefined ( ULong x )
212 {
213 if (x == 0) __asm__ __volatile__( "" ::: "memory" );
214 }
215
216 /*---------------------- malloc ----------------------*/
217
218 /* Generate a replacement for 'fnname' in object 'soname', which calls
219 'vg_replacement' to allocate memory. If that fails, return NULL.
220 */
221 #define ALLOC_or_NULL(soname, fnname, vg_replacement) \
222 \
223 void* VG_REPLACE_FUNCTION_EZU(10010,soname,fnname) (SizeT n); \
224 void* VG_REPLACE_FUNCTION_EZU(10010,soname,fnname) (SizeT n) \
225 { \
226 void* v; \
227 \
228 DO_INIT; \
229 trigger_memcheck_error_if_undefined((ULong)n ); \
230 MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
231 \
232 v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
233 MALLOC_TRACE(" = %p\n", v ); \
234 return v; \
235 }
236
237 #define ZONEALLOC_or_NULL(soname, fnname, vg_replacement) \
238 \
239 void* VG_REPLACE_FUNCTION_EZU(10020,soname,fnname) (void *zone, SizeT n); \
240 void* VG_REPLACE_FUNCTION_EZU(10020,soname,fnname) (void *zone, SizeT n) \
241 { \
242 void* v; \
243 \
244 DO_INIT; \
245 trigger_memcheck_error_if_undefined((ULong)(UWord) zone); \
246 trigger_memcheck_error_if_undefined((ULong) n); \
247 MALLOC_TRACE(#fnname "(%p, %llu)", zone, (ULong)n ); \
248 \
249 v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
250 MALLOC_TRACE(" = %p\n", v ); \
251 return v; \
252 }
253
254
255 /* Generate a replacement for 'fnname' in object 'soname', which calls
256 'vg_replacement' to allocate memory. If that fails, it bombs the
257 system.
258 */
259 #define ALLOC_or_BOMB(soname, fnname, vg_replacement) \
260 \
261 void* VG_REPLACE_FUNCTION_EZU(10030,soname,fnname) (SizeT n); \
262 void* VG_REPLACE_FUNCTION_EZU(10030,soname,fnname) (SizeT n) \
263 { \
264 void* v; \
265 \
266 DO_INIT; \
267 trigger_memcheck_error_if_undefined((ULong) n); \
268 MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
269 \
270 v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
271 MALLOC_TRACE(" = %p\n", v ); \
272 if (NULL == v) { \
273 VALGRIND_PRINTF( \
274 "new/new[] failed and should throw an exception, but Valgrind\n"); \
275 VALGRIND_PRINTF_BACKTRACE( \
276 " cannot throw exceptions and so is aborting instead. Sorry.\n"); \
277 my_exit(1); \
278 } \
279 return v; \
280 }
281
282 // Each of these lines generates a replacement function:
283 // (from_so, from_fn, v's replacement)
284 // For some lines, we will also define a replacement function
285 // whose only purpose is to be a soname synonym place holder
286 // that can be replaced using --soname-synonyms.
287 #define SO_SYN_MALLOC VG_SO_SYN(somalloc)
288
289 // malloc
290 #if defined(VGO_linux)
291 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, malloc, malloc);
292 ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc, malloc);
293 ALLOC_or_NULL(SO_SYN_MALLOC, malloc, malloc);
294
295 #elif defined(VGO_darwin)
296 ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc, malloc);
297 ALLOC_or_NULL(SO_SYN_MALLOC, malloc, malloc);
298 ZONEALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc_zone_malloc, malloc);
299 ZONEALLOC_or_NULL(SO_SYN_MALLOC, malloc_zone_malloc, malloc);
300
301 #endif
302
303
304 /*---------------------- new ----------------------*/
305
306 #if defined(VGO_linux)
307 // operator new(unsigned int), not mangled (for gcc 2.96)
308 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, builtin_new, __builtin_new);
309 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, builtin_new, __builtin_new);
310 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, __builtin_new, __builtin_new);
311 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, __builtin_new, __builtin_new);
312 // operator new(unsigned int), GNU mangling
313 #if VG_WORDSIZE == 4
314 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj, __builtin_new);
315 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwj, __builtin_new);
316 ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwj, __builtin_new);
317 #endif
318 // operator new(unsigned long), GNU mangling
319 #if VG_WORDSIZE == 8
320 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm, __builtin_new);
321 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwm, __builtin_new);
322 ALLOC_or_BOMB(SO_SYN_MALLOC, _Znwm, __builtin_new);
323 #endif
324
325 #elif defined(VGO_darwin)
326 // operator new(unsigned int), GNU mangling
327 #if VG_WORDSIZE == 4
328 //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj, __builtin_new);
329 //ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwj, __builtin_new);
330 #endif
331 // operator new(unsigned long), GNU mangling
332 #if 1 // FIXME: is this right?
333 //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm, __builtin_new);
334 //ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwm, __builtin_new);
335 #endif
336
337 #endif
338
339
340 /*---------------------- new nothrow ----------------------*/
341
342 #if defined(VGO_linux)
343 // operator new(unsigned, std::nothrow_t const&), GNU mangling
344 #if VG_WORDSIZE == 4
345 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new);
346 ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new);
347 ALLOC_or_NULL(SO_SYN_MALLOC, _ZnwjRKSt9nothrow_t, __builtin_new);
348 #endif
349 // operator new(unsigned long, std::nothrow_t const&), GNU mangling
350 #if VG_WORDSIZE == 8
351 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new);
352 ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new);
353 ALLOC_or_NULL(SO_SYN_MALLOC, _ZnwmRKSt9nothrow_t, __builtin_new);
354 #endif
355
356 #elif defined(VGO_darwin)
357 // operator new(unsigned, std::nothrow_t const&), GNU mangling
358 #if VG_WORDSIZE == 4
359 //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new);
360 //ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new);
361 #endif
362 // operator new(unsigned long, std::nothrow_t const&), GNU mangling
363 #if 1 // FIXME: is this right?
364 //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new);
365 //ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new);
366 #endif
367
368 #endif
369
370
371 /*---------------------- new [] ----------------------*/
372
373 #if defined(VGO_linux)
374 // operator new[](unsigned int), not mangled (for gcc 2.96)
375 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, __builtin_vec_new, __builtin_vec_new );
376 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, __builtin_vec_new, __builtin_vec_new );
377 // operator new[](unsigned int), GNU mangling
378 #if VG_WORDSIZE == 4
379 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj, __builtin_vec_new );
380 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znaj, __builtin_vec_new );
381 ALLOC_or_BOMB(SO_SYN_MALLOC, _Znaj, __builtin_vec_new );
382 #endif
383 // operator new[](unsigned long), GNU mangling
384 #if VG_WORDSIZE == 8
385 ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam, __builtin_vec_new );
386 ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znam, __builtin_vec_new );
387 ALLOC_or_BOMB(SO_SYN_MALLOC, _Znam, __builtin_vec_new );
388 #endif
389
390 #elif defined(VGO_darwin)
391 // operator new[](unsigned int), GNU mangling
392 #if VG_WORDSIZE == 4
393 //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj, __builtin_vec_new );
394 //ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znaj, __builtin_vec_new );
395 #endif
396 // operator new[](unsigned long), GNU mangling
397 #if 1 // FIXME: is this right?
398 //ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam, __builtin_vec_new );
399 //ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znam, __builtin_vec_new );
400 #endif
401
402 #endif
403
404
405 /*---------------------- new [] nothrow ----------------------*/
406
407 #if defined(VGO_linux)
408 // operator new[](unsigned, std::nothrow_t const&), GNU mangling
409 #if VG_WORDSIZE == 4
410 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
411 ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
412 ALLOC_or_NULL(SO_SYN_MALLOC, _ZnajRKSt9nothrow_t, __builtin_vec_new );
413 #endif
414 // operator new[](unsigned long, std::nothrow_t const&), GNU mangling
415 #if VG_WORDSIZE == 8
416 ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
417 ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
418 ALLOC_or_NULL(SO_SYN_MALLOC, _ZnamRKSt9nothrow_t, __builtin_vec_new );
419 #endif
420
421 #elif defined(VGO_darwin)
422 // operator new[](unsigned, std::nothrow_t const&), GNU mangling
423 #if VG_WORDSIZE == 4
424 //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
425 //ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new );
426 #endif
427 // operator new[](unsigned long, std::nothrow_t const&), GNU mangling
428 #if 1 // FIXME: is this right?
429 //ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
430 //ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new );
431 #endif
432
433 #endif
434
435
436 /*---------------------- free ----------------------*/
437
438 /* Generate a replacement for 'fnname' in object 'soname', which calls
439 'vg_replacement' to free previously allocated memory.
440 */
441 #define ZONEFREE(soname, fnname, vg_replacement) \
442 \
443 void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p); \
444 void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p) \
445 { \
446 DO_INIT; \
447 trigger_memcheck_error_if_undefined((ULong)(UWord) zone); \
448 MALLOC_TRACE(#fnname "(%p, %p)\n", zone, p ); \
449 if (p == NULL) \
450 return; \
451 (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
452 }
453
454 #define FREE(soname, fnname, vg_replacement) \
455 \
456 void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p); \
457 void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p) \
458 { \
459 DO_INIT; \
460 MALLOC_TRACE(#fnname "(%p)\n", p ); \
461 if (p == NULL) \
462 return; \
463 (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \
464 }
465
466
467 #if defined(VGO_linux)
468 FREE(VG_Z_LIBSTDCXX_SONAME, free, free );
469 FREE(VG_Z_LIBC_SONAME, free, free );
470 FREE(SO_SYN_MALLOC, free, free );
471
472 #elif defined(VGO_darwin)
473 FREE(VG_Z_LIBC_SONAME, free, free );
474 FREE(SO_SYN_MALLOC, free, free );
475 ZONEFREE(VG_Z_LIBC_SONAME, malloc_zone_free, free );
476 ZONEFREE(SO_SYN_MALLOC, malloc_zone_free, free );
477
478 #endif
479
480
481 /*---------------------- cfree ----------------------*/
482
483 // cfree
484 #if defined(VGO_linux)
485 FREE(VG_Z_LIBSTDCXX_SONAME, cfree, free );
486 FREE(VG_Z_LIBC_SONAME, cfree, free );
487 FREE(SO_SYN_MALLOC, cfree, free );
488
489 #elif defined(VGO_darwin)
490 //FREE(VG_Z_LIBSTDCXX_SONAME, cfree, free );
491 //FREE(VG_Z_LIBC_SONAME, cfree, free );
492
493 #endif
494
495
496 /*---------------------- delete ----------------------*/
497
498 #if defined(VGO_linux)
499 // operator delete(void*), not mangled (for gcc 2.96)
500 FREE(VG_Z_LIBSTDCXX_SONAME, __builtin_delete, __builtin_delete );
501 FREE(VG_Z_LIBC_SONAME, __builtin_delete, __builtin_delete );
502 // operator delete(void*), GNU mangling
503 FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv, __builtin_delete );
504 FREE(VG_Z_LIBC_SONAME, _ZdlPv, __builtin_delete );
505 FREE(SO_SYN_MALLOC, _ZdlPv, __builtin_delete );
506
507 #elif defined(VGO_darwin)
508 // operator delete(void*), GNU mangling
509 //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv, __builtin_delete );
510 //FREE(VG_Z_LIBC_SONAME, _ZdlPv, __builtin_delete );
511
512 #endif
513
514
515 /*---------------------- delete nothrow ----------------------*/
516
517 #if defined(VGO_linux)
518 // operator delete(void*, std::nothrow_t const&), GNU mangling
519 FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete );
520 FREE(VG_Z_LIBC_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete );
521 FREE(SO_SYN_MALLOC, _ZdlPvRKSt9nothrow_t, __builtin_delete );
522
523 #elif defined(VGO_darwin)
524 // operator delete(void*, std::nothrow_t const&), GNU mangling
525 //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete );
526 //FREE(VG_Z_LIBC_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete );
527
528 #endif
529
530
531 /*---------------------- delete [] ----------------------*/
532
533 #if defined(VGO_linux)
534 // operator delete[](void*), not mangled (for gcc 2.96)
535 FREE(VG_Z_LIBSTDCXX_SONAME, __builtin_vec_delete, __builtin_vec_delete );
536 FREE(VG_Z_LIBC_SONAME, __builtin_vec_delete, __builtin_vec_delete );
537 // operator delete[](void*), GNU mangling
538 FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete );
539 FREE(VG_Z_LIBC_SONAME, _ZdaPv, __builtin_vec_delete );
540 FREE(SO_SYN_MALLOC, _ZdaPv, __builtin_vec_delete );
541
542 #elif defined(VGO_darwin)
543 // operator delete[](void*), not mangled (for gcc 2.96)
544 //FREE(VG_Z_LIBSTDCXX_SONAME, __builtin_vec_delete, __builtin_vec_delete );
545 //FREE(VG_Z_LIBC_SONAME, __builtin_vec_delete, __builtin_vec_delete );
546 // operator delete[](void*), GNU mangling
547 //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete );
548 //FREE(VG_Z_LIBC_SONAME, _ZdaPv, __builtin_vec_delete );
549
550 #endif
551
552
553 /*---------------------- delete [] nothrow ----------------------*/
554
555 #if defined(VGO_linux)
556 // operator delete[](void*, std::nothrow_t const&), GNU mangling
557 FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
558 FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
559 FREE(SO_SYN_MALLOC, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
560
561 #elif defined(VGO_darwin)
562 // operator delete[](void*, std::nothrow_t const&), GNU mangling
563 //FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
564 //FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete );
565
566 #endif
567
568
569 /*---------------------- calloc ----------------------*/
570
571 #define ZONECALLOC(soname, fnname) \
572 \
573 void* VG_REPLACE_FUNCTION_EZU(10060,soname,fnname) \
574 ( void *zone, SizeT nmemb, SizeT size ); \
575 void* VG_REPLACE_FUNCTION_EZU(10060,soname,fnname) \
576 ( void *zone, SizeT nmemb, SizeT size ) \
577 { \
578 void* v; \
579 \
580 DO_INIT; \
581 trigger_memcheck_error_if_undefined((ULong)(UWord) zone); \
582 trigger_memcheck_error_if_undefined((ULong) nmemb); \
583 trigger_memcheck_error_if_undefined((ULong) size); \
584 MALLOC_TRACE("zone_calloc(%p, %llu,%llu)", zone, (ULong)nmemb, (ULong)size ); \
585 \
586 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
587 MALLOC_TRACE(" = %p\n", v ); \
588 return v; \
589 }
590
591 #define CALLOC(soname, fnname) \
592 \
593 void* VG_REPLACE_FUNCTION_EZU(10070,soname,fnname) \
594 ( SizeT nmemb, SizeT size ); \
595 void* VG_REPLACE_FUNCTION_EZU(10070,soname,fnname) \
596 ( SizeT nmemb, SizeT size ) \
597 { \
598 void* v; \
599 \
600 DO_INIT; \
601 MALLOC_TRACE("calloc(%llu,%llu)", (ULong)nmemb, (ULong)size ); \
602 \
603 /* Protect against overflow. See bug 24078. (that bug number is
604 invalid. Which one really?) */ \
605 /* But don't use division, since that produces an external symbol
606 reference on ARM, in the form of a call to __aeabi_uidiv. It's
607 normally OK, because ld.so manages to resolve it to something in the
608 executable, or one of its shared objects. But that isn't guaranteed
609 to be the case, and it has been observed to fail in rare cases, eg:
610 echo x | valgrind /bin/sed -n "s/.*-\>\ //p"
611 So instead compute the high word of the product and check it is zero. */ \
612 if (umulHW(size, nmemb) != 0) return NULL; \
613 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
614 MALLOC_TRACE(" = %p\n", v ); \
615 return v; \
616 }
617
618 #if defined(VGO_linux)
619 CALLOC(VG_Z_LIBC_SONAME, calloc);
620 CALLOC(SO_SYN_MALLOC, calloc);
621
622 #elif defined(VGO_darwin)
623 CALLOC(VG_Z_LIBC_SONAME, calloc);
624 CALLOC(SO_SYN_MALLOC, calloc);
625 ZONECALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc);
626 ZONECALLOC(SO_SYN_MALLOC, malloc_zone_calloc);
627
628 #endif
629
630
631 /*---------------------- realloc ----------------------*/
632
633 #define ZONEREALLOC(soname, fnname) \
634 \
635 void* VG_REPLACE_FUNCTION_EZU(10080,soname,fnname) \
636 ( void *zone, void* ptrV, SizeT new_size ); \
637 void* VG_REPLACE_FUNCTION_EZU(10080,soname,fnname) \
638 ( void *zone, void* ptrV, SizeT new_size ) \
639 { \
640 void* v; \
641 \
642 DO_INIT; \
643 MALLOC_TRACE("zone_realloc(%p,%p,%llu)", zone, ptrV, (ULong)new_size ); \
644 \
645 if (ptrV == NULL) \
646 /* We need to call a malloc-like function; so let's use \
647 one which we know exists. GrP fixme use zonemalloc instead? */ \
648 return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
649 (new_size); \
650 if (new_size <= 0) { \
651 VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
652 MALLOC_TRACE(" = 0\n"); \
653 return NULL; \
654 } \
655 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
656 MALLOC_TRACE(" = %p\n", v ); \
657 return v; \
658 }
659
660 #define REALLOC(soname, fnname) \
661 \
662 void* VG_REPLACE_FUNCTION_EZU(10090,soname,fnname) \
663 ( void* ptrV, SizeT new_size );\
664 void* VG_REPLACE_FUNCTION_EZU(10090,soname,fnname) \
665 ( void* ptrV, SizeT new_size ) \
666 { \
667 void* v; \
668 \
669 DO_INIT; \
670 MALLOC_TRACE("realloc(%p,%llu)", ptrV, (ULong)new_size ); \
671 \
672 if (ptrV == NULL) \
673 /* We need to call a malloc-like function; so let's use \
674 one which we know exists. */ \
675 return VG_REPLACE_FUNCTION_EZU(10010,VG_Z_LIBC_SONAME,malloc) \
676 (new_size); \
677 if (new_size <= 0) { \
678 VG_REPLACE_FUNCTION_EZU(10050,VG_Z_LIBC_SONAME,free)(ptrV); \
679 MALLOC_TRACE(" = 0\n"); \
680 return NULL; \
681 } \
682 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \
683 MALLOC_TRACE(" = %p\n", v ); \
684 return v; \
685 }
686
687 #if defined(VGO_linux)
688 REALLOC(VG_Z_LIBC_SONAME, realloc);
689 REALLOC(SO_SYN_MALLOC, realloc);
690
691 #elif defined(VGO_darwin)
692 REALLOC(VG_Z_LIBC_SONAME, realloc);
693 REALLOC(SO_SYN_MALLOC, realloc);
694 ZONEREALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc);
695 ZONEREALLOC(SO_SYN_MALLOC, malloc_zone_realloc);
696
697 #endif
698
699
700 /*---------------------- memalign ----------------------*/
701
702 #define ZONEMEMALIGN(soname, fnname) \
703 \
704 void* VG_REPLACE_FUNCTION_EZU(10100,soname,fnname) \
705 ( void *zone, SizeT alignment, SizeT n ); \
706 void* VG_REPLACE_FUNCTION_EZU(10100,soname,fnname) \
707 ( void *zone, SizeT alignment, SizeT n ) \
708 { \
709 void* v; \
710 \
711 DO_INIT; \
712 trigger_memcheck_error_if_undefined((ULong)(UWord) zone); \
713 trigger_memcheck_error_if_undefined((ULong) n); \
714 MALLOC_TRACE("zone_memalign(%p, al %llu, size %llu)", \
715 zone, (ULong)alignment, (ULong)n ); \
716 \
717 /* Round up to minimum alignment if necessary. */ \
718 if (alignment < VG_MIN_MALLOC_SZB) \
719 alignment = VG_MIN_MALLOC_SZB; \
720 \
721 /* Round up to nearest power-of-two if necessary (like glibc). */ \
722 while (0 != (alignment & (alignment - 1))) alignment++; \
723 \
724 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
725 MALLOC_TRACE(" = %p\n", v ); \
726 return v; \
727 }
728
729 #define MEMALIGN(soname, fnname) \
730 \
731 void* VG_REPLACE_FUNCTION_EZU(10110,soname,fnname) \
732 ( SizeT alignment, SizeT n ); \
733 void* VG_REPLACE_FUNCTION_EZU(10110,soname,fnname) \
734 ( SizeT alignment, SizeT n ) \
735 { \
736 void* v; \
737 \
738 DO_INIT; \
739 trigger_memcheck_error_if_undefined((ULong) n); \
740 MALLOC_TRACE("memalign(al %llu, size %llu)", \
741 (ULong)alignment, (ULong)n ); \
742 \
743 /* Round up to minimum alignment if necessary. */ \
744 if (alignment < VG_MIN_MALLOC_SZB) \
745 alignment = VG_MIN_MALLOC_SZB; \
746 \
747 /* Round up to nearest power-of-two if necessary (like glibc). */ \
748 while (0 != (alignment & (alignment - 1))) alignment++; \
749 \
750 v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \
751 MALLOC_TRACE(" = %p\n", v ); \
752 return v; \
753 }
754
755 #if defined(VGO_linux)
756 MEMALIGN(VG_Z_LIBC_SONAME, memalign);
757 MEMALIGN(SO_SYN_MALLOC, memalign);
758
759 #elif defined(VGO_darwin)
760 MEMALIGN(VG_Z_LIBC_SONAME, memalign);
761 MEMALIGN(SO_SYN_MALLOC, memalign);
762 ZONEMEMALIGN(VG_Z_LIBC_SONAME, malloc_zone_memalign);
763 ZONEMEMALIGN(SO_SYN_MALLOC, malloc_zone_memalign);
764
765 #endif
766
767
768 /*---------------------- valloc ----------------------*/
769
770 #define VALLOC(soname, fnname) \
771 \
772 void* VG_REPLACE_FUNCTION_EZU(10120,soname,fnname) ( SizeT size ); \
773 void* VG_REPLACE_FUNCTION_EZU(10120,soname,fnname) ( SizeT size ) \
774 { \
775 static int pszB = 0; \
776 if (pszB == 0) \
777 pszB = my_getpagesize(); \
778 return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
779 ((SizeT)pszB, size); \
780 }
781
782 #define ZONEVALLOC(soname, fnname) \
783 \
784 void* VG_REPLACE_FUNCTION_EZU(10130,soname,fnname) \
785 ( void *zone, SizeT size ); \
786 void* VG_REPLACE_FUNCTION_EZU(10130,soname,fnname) \
787 ( void *zone, SizeT size ) \
788 { \
789 static int pszB = 0; \
790 if (pszB == 0) \
791 pszB = my_getpagesize(); \
792 trigger_memcheck_error_if_undefined((ULong)(UWord) zone); \
793 return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
794 ((SizeT)pszB, size); \
795 }
796
797 #if defined(VGO_linux)
798 VALLOC(VG_Z_LIBC_SONAME, valloc);
799 VALLOC(SO_SYN_MALLOC, valloc);
800
801 #elif defined(VGO_darwin)
802 VALLOC(VG_Z_LIBC_SONAME, valloc);
803 VALLOC(SO_SYN_MALLOC, valloc);
804 ZONEVALLOC(VG_Z_LIBC_SONAME, malloc_zone_valloc);
805 ZONEVALLOC(SO_SYN_MALLOC, malloc_zone_valloc);
806
807 #endif
808
809
810 /*---------------------- mallopt ----------------------*/
811
812 /* Various compatibility wrapper functions, for glibc and libstdc++. */
813
814 #define MALLOPT(soname, fnname) \
815 \
816 int VG_REPLACE_FUNCTION_EZU(10140,soname,fnname) ( int cmd, int value ); \
817 int VG_REPLACE_FUNCTION_EZU(10140,soname,fnname) ( int cmd, int value ) \
818 { \
819 /* In glibc-2.2.4, 1 denotes a successful return value for \
820 mallopt */ \
821 trigger_memcheck_error_if_undefined((ULong) cmd); \
822 trigger_memcheck_error_if_undefined((ULong) value); \
823 return 1; \
824 }
825
826 #if defined(VGO_linux)
827 MALLOPT(VG_Z_LIBC_SONAME, mallopt);
828 MALLOPT(SO_SYN_MALLOC, mallopt);
829
830 #elif defined(VGO_darwin)
831 //MALLOPT(VG_Z_LIBC_SONAME, mallopt);
832
833 #endif
834
835
836 /*---------------------- malloc_trim ----------------------*/
837 // Documentation says:
838 // malloc_trim(size_t pad);
839 //
840 // If possible, gives memory back to the system (via negative arguments to
841 // sbrk) if there is unused memory at the `high' end of the malloc pool.
842 // You can call this after freeing large blocks of memory to potentially
843 // reduce the system-level memory requirements of a program. However, it
844 // cannot guarantee to reduce memory. Under some allocation patterns,
845 // some large free blocks of memory will be locked between two used
846 // chunks, so they cannot be given back to the system.
847 //
848 // The `pad' argument to malloc_trim represents the amount of free
849 // trailing space to leave untrimmed. If this argument is zero, only the
850 // minimum amount of memory to maintain internal data structures will be
851 // left (one page or less). Non-zero arguments can be supplied to maintain
852 // enough trailing space to service future expected allocations without
853 // having to re-obtain memory from the system.
854 //
855 // Malloc_trim returns 1 if it actually released any memory, else 0. On
856 // systems that do not support "negative sbrks", it will always return 0.
857 //
858 // For simplicity, we always return 0.
859 #define MALLOC_TRIM(soname, fnname) \
860 \
861 int VG_REPLACE_FUNCTION_EZU(10150,soname,fnname) ( SizeT pad ); \
862 int VG_REPLACE_FUNCTION_EZU(10150,soname,fnname) ( SizeT pad ) \
863 { \
864 /* 0 denotes that malloc_trim() either wasn't able \
865 to do anything, or was not implemented */ \
866 trigger_memcheck_error_if_undefined((ULong) pad); \
867 return 0; \
868 }
869
870 #if defined(VGO_linux)
871 MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
872 MALLOC_TRIM(SO_SYN_MALLOC, malloc_trim);
873
874 #elif defined(VGO_darwin)
875 //MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim);
876
877 #endif
878
879
880 /*---------------------- posix_memalign ----------------------*/
881
882 #define POSIX_MEMALIGN(soname, fnname) \
883 \
884 int VG_REPLACE_FUNCTION_EZU(10160,soname,fnname) \
885 ( void **memptr, SizeT alignment, SizeT size ); \
886 int VG_REPLACE_FUNCTION_EZU(10160,soname,fnname) \
887 ( void **memptr, SizeT alignment, SizeT size ) \
888 { \
889 void *mem; \
890 \
891 /* Test whether the alignment argument is valid. It must be \
892 a power of two multiple of sizeof (void *). */ \
893 if (alignment % sizeof (void *) != 0 \
894 || (alignment & (alignment - 1)) != 0) \
895 return VKI_EINVAL; \
896 \
897 mem = VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
898 (alignment, size); \
899 \
900 if (mem != NULL) { \
901 *memptr = mem; \
902 return 0; \
903 } \
904 \
905 return VKI_ENOMEM; \
906 }
907
908 #if defined(VGO_linux)
909 POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
910 POSIX_MEMALIGN(SO_SYN_MALLOC, posix_memalign);
911
912 #elif defined(VGO_darwin)
913 //POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
914
915 #endif
916
917
918 /*---------------------- malloc_usable_size ----------------------*/
919
920 #define MALLOC_USABLE_SIZE(soname, fnname) \
921 \
922 SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ); \
923 SizeT VG_REPLACE_FUNCTION_EZU(10170,soname,fnname) ( void* p ) \
924 { \
925 SizeT pszB; \
926 \
927 DO_INIT; \
928 MALLOC_TRACE("malloc_usable_size(%p)", p ); \
929 if (NULL == p) \
930 return 0; \
931 \
932 pszB = (SizeT)VALGRIND_NON_SIMD_CALL1( info.tl_malloc_usable_size, p ); \
933 MALLOC_TRACE(" = %llu\n", (ULong)pszB ); \
934 \
935 return pszB; \
936 }
937
938 #if defined(VGO_linux)
939 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
940 MALLOC_USABLE_SIZE(SO_SYN_MALLOC, malloc_usable_size);
941 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size);
942 MALLOC_USABLE_SIZE(SO_SYN_MALLOC, malloc_size);
943 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
944 || defined(VGPV_mips32_linux_android)
945 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, dlmalloc_usable_size);
946 MALLOC_USABLE_SIZE(SO_SYN_MALLOC, dlmalloc_usable_size);
947 # endif
948
949 #elif defined(VGO_darwin)
950 //MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size);
951 MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_size);
952 MALLOC_USABLE_SIZE(SO_SYN_MALLOC, malloc_size);
953
954 #endif
955
956
957 /*---------------------- (unimplemented) ----------------------*/
958
959 /* Bomb out if we get any of these. */
960
panic(const char * str)961 static void panic(const char *str)
962 {
963 VALGRIND_PRINTF_BACKTRACE("Program aborting because of call to %s\n", str);
964 my_exit(99);
965 *(volatile int *)0 = 'x';
966 }
967
968 #define PANIC(soname, fnname) \
969 \
970 void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void ); \
971 void VG_REPLACE_FUNCTION_EZU(10180,soname,fnname) ( void ) \
972 { \
973 panic(#fnname); \
974 }
975
976 #if defined(VGO_linux)
977 PANIC(VG_Z_LIBC_SONAME, pvalloc);
978 PANIC(VG_Z_LIBC_SONAME, malloc_get_state);
979 PANIC(VG_Z_LIBC_SONAME, malloc_set_state);
980
981 #elif defined(VGO_darwin)
982 PANIC(VG_Z_LIBC_SONAME, pvalloc);
983 PANIC(VG_Z_LIBC_SONAME, malloc_get_state);
984 PANIC(VG_Z_LIBC_SONAME, malloc_set_state);
985
986 #endif
987
988
989 #define MALLOC_STATS(soname, fnname) \
990 \
991 void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ); \
992 void VG_REPLACE_FUNCTION_EZU(10190,soname,fnname) ( void ) \
993 { \
994 /* Valgrind's malloc_stats implementation does nothing. */ \
995 }
996
997 #if defined(VGO_linux)
998 MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats);
999 MALLOC_STATS(SO_SYN_MALLOC, malloc_stats);
1000
1001 #elif defined(VGO_darwin)
1002 //MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats);
1003
1004 #endif
1005
1006
1007 /*---------------------- mallinfo ----------------------*/
1008
1009 // mi must be static; if it is auto then Memcheck thinks it is
1010 // uninitialised when used by the caller of this function, because Memcheck
1011 // doesn't know that the call to mallinfo fills in mi.
1012 #define MALLINFO(soname, fnname) \
1013 \
1014 struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ); \
1015 struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ) \
1016 { \
1017 static struct vg_mallinfo mi; \
1018 DO_INIT; \
1019 MALLOC_TRACE("mallinfo()\n"); \
1020 (void)VALGRIND_NON_SIMD_CALL1( info.mallinfo, &mi ); \
1021 return mi; \
1022 }
1023
1024 #if defined(VGO_linux)
1025 MALLINFO(VG_Z_LIBC_SONAME, mallinfo);
1026 MALLINFO(SO_SYN_MALLOC, mallinfo);
1027
1028 #elif defined(VGO_darwin)
1029 //MALLINFO(VG_Z_LIBC_SONAME, mallinfo);
1030
1031 #endif
1032
1033
1034 /*------------------ Darwin zone stuff ------------------*/
1035
1036 #if defined(VGO_darwin)
1037
my_malloc_size(void * zone,void * ptr)1038 static size_t my_malloc_size ( void* zone, void* ptr )
1039 {
1040 /* Implement "malloc_size" by handing the request through to the
1041 tool's .tl_usable_size method. */
1042 DO_INIT;
1043 trigger_memcheck_error_if_undefined((ULong)(UWord) zone);
1044 trigger_memcheck_error_if_undefined((ULong)(UWord) ptr);
1045 size_t res = (size_t)VALGRIND_NON_SIMD_CALL1(
1046 info.tl_malloc_usable_size, ptr);
1047 return res;
1048 }
1049
1050 /* Note that the (void*) casts below are a kludge which stops
1051 compilers complaining about the fact that the the replacement
1052 functions aren't really of the right type. */
1053 static vki_malloc_zone_t vg_default_zone = {
1054 NULL, // reserved1
1055 NULL, // reserved2
1056 (void*)my_malloc_size, // JRS fixme: is this right?
1057 (void*)VG_REPLACE_FUNCTION_EZU(10020,VG_Z_LIBC_SONAME,malloc_zone_malloc),
1058 (void*)VG_REPLACE_FUNCTION_EZU(10060,VG_Z_LIBC_SONAME,malloc_zone_calloc),
1059 (void*)VG_REPLACE_FUNCTION_EZU(10130,VG_Z_LIBC_SONAME,malloc_zone_valloc),
1060 (void*)VG_REPLACE_FUNCTION_EZU(10040,VG_Z_LIBC_SONAME,malloc_zone_free),
1061 (void*)VG_REPLACE_FUNCTION_EZU(10080,VG_Z_LIBC_SONAME,malloc_zone_realloc),
1062 NULL, // GrP fixme: destroy
1063 "ValgrindMallocZone",
1064 NULL, // batch_malloc
1065 NULL, // batch_free
1066 NULL, // GrP fixme: introspect
1067 2, // version (GrP fixme 3?)
1068 NULL, /* memalign */ // DDD: this field exists in Mac OS 10.6, but not 10.5.
1069 NULL, /* free_definite_size */
1070 NULL, /* pressure_relief */
1071 };
1072
1073
1074 #define DEFAULT_ZONE(soname, fnname) \
1075 \
1076 void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ); \
1077 void *VG_REPLACE_FUNCTION_EZU(10210,soname,fnname) ( void ) \
1078 { \
1079 return &vg_default_zone; \
1080 }
1081
1082 DEFAULT_ZONE(VG_Z_LIBC_SONAME, malloc_default_zone);
1083 DEFAULT_ZONE(SO_SYN_MALLOC, malloc_default_zone);
1084
1085
1086 #define ZONE_FROM_PTR(soname, fnname) \
1087 \
1088 void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname) ( void* ptr ); \
1089 void *VG_REPLACE_FUNCTION_EZU(10220,soname,fnname) ( void* ptr ) \
1090 { \
1091 return &vg_default_zone; \
1092 }
1093
1094 ZONE_FROM_PTR(VG_Z_LIBC_SONAME, malloc_zone_from_ptr);
1095 ZONE_FROM_PTR(SO_SYN_MALLOC, malloc_zone_from_ptr);
1096
1097
1098 // GrP fixme bypass libc's use of zone->introspect->check
1099 #define ZONE_CHECK(soname, fnname) \
1100 \
1101 int VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(void* zone); \
1102 int VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(void* zone) \
1103 { \
1104 trigger_memcheck_error_if_undefined((ULong) zone); \
1105 return 1; \
1106 }
1107
1108 //ZONE_CHECK(VG_Z_LIBC_SONAME, malloc_zone_check);
1109
1110 #endif /* defined(VGO_darwin) */
1111
1112
1113 /*------------------ (startup related) ------------------*/
1114
1115 /* All the code in here is unused until this function is called */
1116
1117 __attribute__((constructor))
init(void)1118 static void init(void)
1119 {
1120 // This doesn't look thread-safe, but it should be ok... Bart says:
1121 //
1122 // Every program I know of calls malloc() at least once before calling
1123 // pthread_create(). So init_done gets initialized before any thread is
1124 // created, and is only read when multiple threads are active
1125 // simultaneously. Such an access pattern is safe.
1126 //
1127 // If the assignment to the variable init_done would be triggering a race
1128 // condition, both DRD and Helgrind would report this race.
1129 //
1130 // By the way, although the init() function in
1131 // coregrind/m_replacemalloc/vg_replace_malloc.c has been declared
1132 // __attribute__((constructor)), it is not safe to remove the variable
1133 // init_done. This is because it is possible that malloc() and hence
1134 // init() gets called before shared library initialization finished.
1135 //
1136 if (init_done)
1137 return;
1138
1139 init_done = 1;
1140
1141 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__GET_MALLOCFUNCS, &info,
1142 0, 0, 0, 0);
1143 }
1144
1145 /*--------------------------------------------------------------------*/
1146 /*--- end ---*/
1147 /*--------------------------------------------------------------------*/
1148