blob: 436ee259720962fb0c53cb668e30609007a976c4 [file] [log] [blame]
sewardjcf2b14a2002-04-12 11:49:29 +00001
2/*--------------------------------------------------------------------*/
3/*--- Code which runs on the simulated CPU. ---*/
4/*--- vg_clientfuncs.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjcf2b14a2002-04-12 11:49:29 +000013
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 LICENSE.
30*/
31
32#include "vg_include.h"
33#include "vg_constants.h"
34
35#include "valgrind.h" /* for VALGRIND_MAGIC_SEQUENCE */
36
37
38/* ---------------------------------------------------------------------
39 All the code in this file runs on the SIMULATED CPU. It is
40 intended for various reasons as drop-in replacements for libc
41 functions. These functions have global visibility (obviously) and
42 have no prototypes in vg_include.h, since they are not intended to
43 be called from within Valgrind.
44 ------------------------------------------------------------------ */
45
46/* ---------------------------------------------------------------------
47 Intercepts for the GNU malloc interface.
48 ------------------------------------------------------------------ */
49
50#define SIMPLE_REQUEST1(_qyy_request, _qyy_arg1) \
51 ({unsigned int _qyy_res; \
52 VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
53 _qyy_request, \
54 _qyy_arg1, 0, 0, 0); \
55 _qyy_res; \
56 })
57
58#define SIMPLE_REQUEST2(_qyy_request, _qyy_arg1, _qyy_arg2) \
59 ({unsigned int _qyy_res; \
60 VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
61 _qyy_request, \
62 _qyy_arg1, _qyy_arg2, 0, 0); \
63 _qyy_res; \
64 })
65
66
67/* Below are new versions of malloc, __builtin_new, free,
68 __builtin_delete, calloc and realloc.
69
70 malloc, __builtin_new, free, __builtin_delete, calloc and realloc
71 can be entered either on the real CPU or the simulated one. If on
72 the real one, this is because the dynamic linker is running the
73 static initialisers for C++, before starting up Valgrind itself.
74 In this case it is safe to route calls through to
75 VG_(malloc)/vg_free, since that is self-initialising.
76
77 Once Valgrind is initialised, vg_running_on_simd_CPU becomes True.
78 The call needs to be transferred from the simulated CPU back to the
79 real one and routed to the vg_client_* functions. To do that, the
80 client-request mechanism (in valgrind.h) is used to convey requests
81 to the scheduler.
82*/
83
84/* ALL calls to malloc wind up here. */
sewardj5c3ea672002-04-24 11:37:37 +000085void* malloc ( Int n )
sewardjcf2b14a2002-04-12 11:49:29 +000086{
87 void* v;
88
89 if (VG_(clo_trace_malloc))
90 VG_(printf)("malloc[simd=%d](%d)",
91 (UInt)VG_(running_on_simd_CPU), n );
sewardj5c3ea672002-04-24 11:37:37 +000092 if (n < 0) {
93 v = NULL;
94 VG_(message)(Vg_UserMsg,
95 "Warning: silly arg (%d) to malloc()", n );
sewardjcf2b14a2002-04-12 11:49:29 +000096 } else {
sewardj5c3ea672002-04-24 11:37:37 +000097 if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
98
99 if (VG_(running_on_simd_CPU)) {
100 v = (void*)SIMPLE_REQUEST1(VG_USERREQ__MALLOC, n);
101 } else {
102 v = VG_(malloc)(VG_AR_CLIENT, n);
103 }
sewardjcf2b14a2002-04-12 11:49:29 +0000104 }
105 if (VG_(clo_trace_malloc))
106 VG_(printf)(" = %p\n", v );
107 return (void*)v;
108}
109
110
sewardj5c3ea672002-04-24 11:37:37 +0000111void* __builtin_new ( Int n )
sewardjcf2b14a2002-04-12 11:49:29 +0000112{
113 void* v;
114
115 if (VG_(clo_trace_malloc))
116 VG_(printf)("__builtin_new[simd=%d](%d)",
117 (UInt)VG_(running_on_simd_CPU), n );
sewardj5c3ea672002-04-24 11:37:37 +0000118 if (n < 0) {
119 v = NULL;
120 VG_(message)(Vg_UserMsg,
121 "Warning: silly arg (%d) to __builtin_new()", n );
sewardjcf2b14a2002-04-12 11:49:29 +0000122 } else {
sewardj5c3ea672002-04-24 11:37:37 +0000123 if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
124
125 if (VG_(running_on_simd_CPU)) {
126 v = (void*)SIMPLE_REQUEST1(VG_USERREQ__BUILTIN_NEW, n);
127 } else {
128 v = VG_(malloc)(VG_AR_CLIENT, n);
129 }
sewardjcf2b14a2002-04-12 11:49:29 +0000130 }
131 if (VG_(clo_trace_malloc))
132 VG_(printf)(" = %p\n", v );
133 return v;
134}
135
136
137void* __builtin_vec_new ( Int n )
138{
139 void* v;
140
141 if (VG_(clo_trace_malloc))
142 VG_(printf)("__builtin_vec_new[simd=%d](%d)",
143 (UInt)VG_(running_on_simd_CPU), n );
sewardj5c3ea672002-04-24 11:37:37 +0000144 if (n < 0) {
145 v = NULL;
146 VG_(message)(Vg_UserMsg,
147 "Warning: silly arg (%d) to __builtin_vec_new()", n );
sewardjcf2b14a2002-04-12 11:49:29 +0000148 } else {
sewardj5c3ea672002-04-24 11:37:37 +0000149 if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
150
151 if (VG_(running_on_simd_CPU)) {
152 v = (void*)SIMPLE_REQUEST1(VG_USERREQ__BUILTIN_VEC_NEW, n);
153 } else {
154 v = VG_(malloc)(VG_AR_CLIENT, n);
155 }
sewardjcf2b14a2002-04-12 11:49:29 +0000156 }
157 if (VG_(clo_trace_malloc))
158 VG_(printf)(" = %p\n", v );
159 return v;
160}
161
162
163void free ( void* p )
164{
165 if (VG_(clo_trace_malloc))
166 VG_(printf)("free[simd=%d](%p)\n",
167 (UInt)VG_(running_on_simd_CPU), p );
168 if (p == NULL)
169 return;
170 if (VG_(running_on_simd_CPU)) {
171 (void)SIMPLE_REQUEST1(VG_USERREQ__FREE, p);
172 } else {
173 VG_(free)(VG_AR_CLIENT, p);
174 }
175}
176
177
178void __builtin_delete ( void* p )
179{
180 if (VG_(clo_trace_malloc))
181 VG_(printf)("__builtin_delete[simd=%d](%p)\n",
182 (UInt)VG_(running_on_simd_CPU), p );
183 if (p == NULL)
184 return;
185 if (VG_(running_on_simd_CPU)) {
186 (void)SIMPLE_REQUEST1(VG_USERREQ__BUILTIN_DELETE, p);
187 } else {
188 VG_(free)(VG_AR_CLIENT, p);
189 }
190}
191
192
193void __builtin_vec_delete ( void* p )
194{
195 if (VG_(clo_trace_malloc))
196 VG_(printf)("__builtin_vec_delete[simd=%d](%p)\n",
197 (UInt)VG_(running_on_simd_CPU), p );
198 if (p == NULL)
199 return;
200 if (VG_(running_on_simd_CPU)) {
201 (void)SIMPLE_REQUEST1(VG_USERREQ__BUILTIN_VEC_DELETE, p);
202 } else {
203 VG_(free)(VG_AR_CLIENT, p);
204 }
205}
206
207
sewardj5c3ea672002-04-24 11:37:37 +0000208void* calloc ( Int nmemb, Int size )
sewardjcf2b14a2002-04-12 11:49:29 +0000209{
210 void* v;
211
212 if (VG_(clo_trace_malloc))
213 VG_(printf)("calloc[simd=%d](%d,%d)",
214 (UInt)VG_(running_on_simd_CPU), nmemb, size );
sewardj5c3ea672002-04-24 11:37:37 +0000215 if (nmemb < 0 || size < 0) {
216 v = NULL;
217 VG_(message)(Vg_UserMsg, "Warning: silly args (%d,%d) to calloc()",
218 nmemb, size );
sewardjcf2b14a2002-04-12 11:49:29 +0000219 } else {
sewardj5c3ea672002-04-24 11:37:37 +0000220 if (VG_(running_on_simd_CPU)) {
221 v = (void*)SIMPLE_REQUEST2(VG_USERREQ__CALLOC, nmemb, size);
222 } else {
223 v = VG_(calloc)(VG_AR_CLIENT, nmemb, size);
224 }
sewardjcf2b14a2002-04-12 11:49:29 +0000225 }
226 if (VG_(clo_trace_malloc))
227 VG_(printf)(" = %p\n", v );
228 return v;
229}
230
231
sewardj5c3ea672002-04-24 11:37:37 +0000232void* realloc ( void* ptrV, Int new_size )
sewardjcf2b14a2002-04-12 11:49:29 +0000233{
234 void* v;
235
236 if (VG_(clo_trace_malloc))
237 VG_(printf)("realloc[simd=%d](%p,%d)",
238 (UInt)VG_(running_on_simd_CPU), ptrV, new_size );
239
240 if (VG_(clo_sloppy_malloc))
241 { while ((new_size % 4) > 0) new_size++; }
242
243 if (ptrV == NULL)
244 return malloc(new_size);
sewardj5c3ea672002-04-24 11:37:37 +0000245 if (new_size <= 0) {
sewardjcf2b14a2002-04-12 11:49:29 +0000246 free(ptrV);
247 if (VG_(clo_trace_malloc))
248 VG_(printf)(" = 0\n" );
249 return NULL;
250 }
251 if (VG_(running_on_simd_CPU)) {
252 v = (void*)SIMPLE_REQUEST2(VG_USERREQ__REALLOC, ptrV, new_size);
253 } else {
254 v = VG_(realloc)(VG_AR_CLIENT, ptrV, new_size);
255 }
256 if (VG_(clo_trace_malloc))
257 VG_(printf)(" = %p\n", v );
258 return v;
259}
260
261
262void* memalign ( Int alignment, Int n )
263{
264 void* v;
265
266 if (VG_(clo_trace_malloc))
267 VG_(printf)("memalign[simd=%d](al %d, size %d)",
268 (UInt)VG_(running_on_simd_CPU), alignment, n );
sewardj5c3ea672002-04-24 11:37:37 +0000269 if (n < 0) {
270 v = NULL;
sewardjcf2b14a2002-04-12 11:49:29 +0000271 } else {
sewardj5c3ea672002-04-24 11:37:37 +0000272 if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
273
274 if (VG_(running_on_simd_CPU)) {
275 v = (void*)SIMPLE_REQUEST2(VG_USERREQ__MEMALIGN, alignment, n);
276 } else {
277 v = VG_(malloc_aligned)(VG_AR_CLIENT, alignment, n);
278 }
sewardjcf2b14a2002-04-12 11:49:29 +0000279 }
280 if (VG_(clo_trace_malloc))
281 VG_(printf)(" = %p\n", v );
282 return (void*)v;
283}
284
285
286void* valloc ( Int size )
287{
288 return memalign(VKI_BYTES_PER_PAGE, size);
289}
290
291
292/* Various compatibility wrapper functions, for glibc and libstdc++. */
293void cfree ( void* p )
294{
295 free ( p );
296}
297
298
299int mallopt ( int cmd, int value )
300{
301 /* In glibc-2.2.4, 1 denotes a successful return value for mallopt */
302 return 1;
303}
304
305
306int __posix_memalign ( void **memptr, UInt alignment, UInt size )
307{
308 void *mem;
309
310 /* Test whether the SIZE argument is valid. It must be a power of
311 two multiple of sizeof (void *). */
312 if (size % sizeof (void *) != 0 || (size & (size - 1)) != 0)
313 return VKI_EINVAL /*22*/ /*EINVAL*/;
314
315 mem = memalign (alignment, size);
316
317 if (mem != NULL) {
318 *memptr = mem;
319 return 0;
320 }
321
322 return VKI_ENOMEM /*12*/ /*ENOMEM*/;
323}
324
325
326/* Bomb out if we get any of these. */
327/* HACK: We shouldn't call VG_(panic) or VG_(message) on the simulated
328 CPU. Really we should pass the request in the usual way, and
329 Valgrind itself can do the panic. Too tedious, however.
330*/
331void pvalloc ( void )
332{ VG_(panic)("call to pvalloc\n"); }
333void malloc_stats ( void )
334{ VG_(panic)("call to malloc_stats\n"); }
335void malloc_usable_size ( void )
336{ VG_(panic)("call to malloc_usable_size\n"); }
337void malloc_trim ( void )
338{ VG_(panic)("call to malloc_trim\n"); }
339void malloc_get_state ( void )
340{ VG_(panic)("call to malloc_get_state\n"); }
341void malloc_set_state ( void )
342{ VG_(panic)("call to malloc_set_state\n"); }
343
344void* mallinfo ( void )
345{
346 VG_(message)(Vg_UserMsg,
347 "Warning: incorrectly-handled call to mallinfo()");
348 return NULL;
349}
350
351
352/* ---------------------------------------------------------------------
353 Replace some C lib things with equivs which don't get
354 spurious value warnings. THEY RUN ON SIMD CPU!
355 ------------------------------------------------------------------ */
356
357char* strrchr ( const char* s, int c )
358{
359 UChar ch = (UChar)((UInt)c);
360 UChar* p = (UChar*)s;
361 UChar* last = NULL;
362 while (True) {
363 if (*p == ch) last = p;
364 if (*p == 0) return last;
365 p++;
366 }
367}
368
369char* strchr ( const char* s, int c )
370{
371 UChar ch = (UChar)((UInt)c);
372 UChar* p = (UChar*)s;
373 while (True) {
374 if (*p == ch) return p;
375 if (*p == 0) return NULL;
376 p++;
377 }
378}
379
380char* strcat ( char* dest, const char* src )
381{
382 Char* dest_orig = dest;
383 while (*dest) dest++;
384 while (*src) *dest++ = *src++;
385 *dest = 0;
386 return dest_orig;
387}
388
389unsigned int strlen ( const char* str )
390{
391 UInt i = 0;
392 while (str[i] != 0) i++;
393 return i;
394}
395
396char* strcpy ( char* dest, const char* src )
397{
398 Char* dest_orig = dest;
399 while (*src) *dest++ = *src++;
400 *dest = 0;
401 return dest_orig;
402}
403
404int strncmp ( const char* s1, const char* s2, unsigned int nmax )
405{
406 unsigned int n = 0;
407 while (True) {
408 if (n >= nmax) return 0;
409 if (*s1 == 0 && *s2 == 0) return 0;
410 if (*s1 == 0) return -1;
411 if (*s2 == 0) return 1;
412
413 if (*(UChar*)s1 < *(UChar*)s2) return -1;
414 if (*(UChar*)s1 > *(UChar*)s2) return 1;
415
416 s1++; s2++; n++;
417 }
418}
419
420int strcmp ( const char* s1, const char* s2 )
421{
sewardj80162402002-05-01 23:05:12 +0000422 register char c1, c2;
sewardjcf2b14a2002-04-12 11:49:29 +0000423 while (True) {
sewardj80162402002-05-01 23:05:12 +0000424 c1 = *s1;
425 c2 = *s2;
426 if (c1 != c2) break;
427 if (c1 == 0) break;
sewardjcf2b14a2002-04-12 11:49:29 +0000428 s1++; s2++;
429 }
sewardj80162402002-05-01 23:05:12 +0000430 if (c1 < c2) return -1;
431 if (c1 > c2) return 1;
432 return 0;
sewardjcf2b14a2002-04-12 11:49:29 +0000433}
434
435void* memchr(const void *s, int c, unsigned int n)
436{
437 unsigned int i;
438 UChar c0 = (UChar)c;
439 UChar* p = (UChar*)s;
440 for (i = 0; i < n; i++)
441 if (p[i] == c0) return (void*)(&p[i]);
442 return NULL;
443}
444
445void* memcpy( void *dst, const void *src, unsigned int len )
446{
447 register char *d;
448 register char *s;
449 if ( dst > src ) {
450 d = (char *)dst + len - 1;
451 s = (char *)src + len - 1;
sewardj80162402002-05-01 23:05:12 +0000452 while ( len >= 4 ) {
sewardjcf2b14a2002-04-12 11:49:29 +0000453 *d-- = *s--;
sewardj80162402002-05-01 23:05:12 +0000454 *d-- = *s--;
455 *d-- = *s--;
456 *d-- = *s--;
457 len -= 4;
458 }
459 while ( len-- ) {
460 *d-- = *s--;
461 }
sewardjcf2b14a2002-04-12 11:49:29 +0000462 } else if ( dst < src ) {
463 d = (char *)dst;
464 s = (char *)src;
sewardj80162402002-05-01 23:05:12 +0000465 while ( len >= 4 ) {
sewardjcf2b14a2002-04-12 11:49:29 +0000466 *d++ = *s++;
sewardj80162402002-05-01 23:05:12 +0000467 *d++ = *s++;
468 *d++ = *s++;
469 *d++ = *s++;
470 len -= 4;
471 }
472 while ( len-- ) {
473 *d++ = *s++;
474 }
sewardjcf2b14a2002-04-12 11:49:29 +0000475 }
476 return dst;
477}
478
479/*--------------------------------------------------------------------*/
480/*--- end vg_clientfuncs.c ---*/
481/*--------------------------------------------------------------------*/