blob: ee4cf38e360a8af3a73966193a5c35af4dd0fdc3 [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
sewardja1269e42002-06-26 17:08:01 +0000344
345/* Yet another ugly hack. Cannot include <malloc.h> because we
346 implement functions implemented there with different signatures.
347 This struct definition MUST match the system one. */
348
349/* SVID2/XPG mallinfo structure */
350struct mallinfo {
351 int arena; /* total space allocated from system */
352 int ordblks; /* number of non-inuse chunks */
353 int smblks; /* unused -- always zero */
354 int hblks; /* number of mmapped regions */
355 int hblkhd; /* total space in mmapped regions */
356 int usmblks; /* unused -- always zero */
357 int fsmblks; /* unused -- always zero */
358 int uordblks; /* total allocated space */
359 int fordblks; /* total non-inuse space */
360 int keepcost; /* top-most, releasable (via malloc_trim) space */
361};
362
363struct mallinfo mallinfo ( void )
364{
365 /* Should really try to return something a bit more meaningful */
366 Int i;
367 struct mallinfo mi;
368 UChar* pmi = (UChar*)(&mi);
369 for (i = 0; i < sizeof(mi); i++)
370 pmi[i] = 0;
371 return mi;
sewardjcf2b14a2002-04-12 11:49:29 +0000372}
373
374
375/* ---------------------------------------------------------------------
376 Replace some C lib things with equivs which don't get
377 spurious value warnings. THEY RUN ON SIMD CPU!
378 ------------------------------------------------------------------ */
379
380char* strrchr ( const char* s, int c )
381{
382 UChar ch = (UChar)((UInt)c);
383 UChar* p = (UChar*)s;
384 UChar* last = NULL;
385 while (True) {
386 if (*p == ch) last = p;
387 if (*p == 0) return last;
388 p++;
389 }
390}
391
392char* strchr ( const char* s, int c )
393{
394 UChar ch = (UChar)((UInt)c);
395 UChar* p = (UChar*)s;
396 while (True) {
397 if (*p == ch) return p;
398 if (*p == 0) return NULL;
399 p++;
400 }
401}
402
403char* strcat ( char* dest, const char* src )
404{
405 Char* dest_orig = dest;
406 while (*dest) dest++;
407 while (*src) *dest++ = *src++;
408 *dest = 0;
409 return dest_orig;
410}
411
412unsigned int strlen ( const char* str )
413{
414 UInt i = 0;
415 while (str[i] != 0) i++;
416 return i;
417}
418
419char* strcpy ( char* dest, const char* src )
420{
421 Char* dest_orig = dest;
422 while (*src) *dest++ = *src++;
423 *dest = 0;
424 return dest_orig;
425}
426
427int strncmp ( const char* s1, const char* s2, unsigned int nmax )
428{
429 unsigned int n = 0;
430 while (True) {
431 if (n >= nmax) return 0;
432 if (*s1 == 0 && *s2 == 0) return 0;
433 if (*s1 == 0) return -1;
434 if (*s2 == 0) return 1;
435
436 if (*(UChar*)s1 < *(UChar*)s2) return -1;
437 if (*(UChar*)s1 > *(UChar*)s2) return 1;
438
439 s1++; s2++; n++;
440 }
441}
442
443int strcmp ( const char* s1, const char* s2 )
444{
sewardj80162402002-05-01 23:05:12 +0000445 register char c1, c2;
sewardjcf2b14a2002-04-12 11:49:29 +0000446 while (True) {
sewardj80162402002-05-01 23:05:12 +0000447 c1 = *s1;
448 c2 = *s2;
449 if (c1 != c2) break;
450 if (c1 == 0) break;
sewardjcf2b14a2002-04-12 11:49:29 +0000451 s1++; s2++;
452 }
sewardj80162402002-05-01 23:05:12 +0000453 if (c1 < c2) return -1;
454 if (c1 > c2) return 1;
455 return 0;
sewardjcf2b14a2002-04-12 11:49:29 +0000456}
457
458void* memchr(const void *s, int c, unsigned int n)
459{
460 unsigned int i;
461 UChar c0 = (UChar)c;
462 UChar* p = (UChar*)s;
463 for (i = 0; i < n; i++)
464 if (p[i] == c0) return (void*)(&p[i]);
465 return NULL;
466}
467
468void* memcpy( void *dst, const void *src, unsigned int len )
469{
470 register char *d;
471 register char *s;
472 if ( dst > src ) {
473 d = (char *)dst + len - 1;
474 s = (char *)src + len - 1;
sewardj80162402002-05-01 23:05:12 +0000475 while ( len >= 4 ) {
sewardjcf2b14a2002-04-12 11:49:29 +0000476 *d-- = *s--;
sewardj80162402002-05-01 23:05:12 +0000477 *d-- = *s--;
478 *d-- = *s--;
479 *d-- = *s--;
480 len -= 4;
481 }
482 while ( len-- ) {
483 *d-- = *s--;
484 }
sewardjcf2b14a2002-04-12 11:49:29 +0000485 } else if ( dst < src ) {
486 d = (char *)dst;
487 s = (char *)src;
sewardj80162402002-05-01 23:05:12 +0000488 while ( len >= 4 ) {
sewardjcf2b14a2002-04-12 11:49:29 +0000489 *d++ = *s++;
sewardj80162402002-05-01 23:05:12 +0000490 *d++ = *s++;
491 *d++ = *s++;
492 *d++ = *s++;
493 len -= 4;
494 }
495 while ( len-- ) {
496 *d++ = *s++;
497 }
sewardjcf2b14a2002-04-12 11:49:29 +0000498 }
499 return dst;
500}
501
502/*--------------------------------------------------------------------*/
503/*--- end vg_clientfuncs.c ---*/
504/*--------------------------------------------------------------------*/