~bkerensa/ubuntu/raring/valgrind/merge-from-deb

« back to all changes in this revision

Viewing changes to memcheck/mc_replace_strmem.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrés Roldán
  • Date: 2008-06-13 02:31:40 UTC
  • mto: (1.4.1 upstream) (2.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20080613023140-iwk33rz9rhvfkr96
Import upstream version 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
   This file is part of MemCheck, a heavyweight Valgrind tool for
10
10
   detecting memory errors.
11
11
 
12
 
   Copyright (C) 2000-2006 Julian Seward 
 
12
   Copyright (C) 2000-2007 Julian Seward 
13
13
      jseward@acm.org
14
14
 
15
15
   This program is free software; you can redistribute it and/or
89
89
 
90
90
// This is a macro rather than a function because we don't want to have an
91
91
// extra function in the stack trace.
92
 
#define RECORD_OVERLAP_ERROR(s, p_extra) \
 
92
#define RECORD_OVERLAP_ERROR(s, src, dst, len) \
93
93
{ \
94
94
   Word unused_res; \
95
95
   VALGRIND_DO_CLIENT_REQUEST(unused_res, 0, \
96
96
                              _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \
97
 
                              s, p_extra, 0, 0, 0); \
98
 
}
99
 
 
100
 
static __inline__
101
 
void complain2 ( Char* s, char* dst, const char* src )
102
 
{
103
 
   OverlapExtra extra = {
104
 
      .src = (Addr)src, .dst = (Addr)dst, .len = -1,
105
 
   };
106
 
   RECORD_OVERLAP_ERROR( s, &extra );
107
 
}
108
 
 
109
 
static __inline__
110
 
void complain3 ( Char* s, void* dst, const void* src, int n )
111
 
{
112
 
   /* Must wrap it up here, because we cannot pass 4 args to core */
113
 
   OverlapExtra extra = {
114
 
      .src = (Addr)src, .dst = (Addr)dst, .len = n,
115
 
   };
116
 
   RECORD_OVERLAP_ERROR( s, &extra );
117
 
}
118
 
 
119
 
// Some handy Z-encoded names
120
 
#define  m_libc_so_star          libcZdsoZa                 // libc.so*
 
97
                              s, src, dst, len, 0); \
 
98
}
 
99
 
 
100
/* --------- Some handy Z-encoded names. --------- */
 
101
 
 
102
/* --- Soname of the standard C library. --- */
 
103
 
 
104
#if defined(VGO_linux)
 
105
#  define  m_libc_soname     libcZdsoZa              // libc.so*
 
106
#elif defined(VGP_ppc32_aix5)
 
107
   /* AIX has both /usr/lib/libc.a and /usr/lib/libc_r.a. */
 
108
#  define  m_libc_soname     libcZaZdaZLshrZdoZR     // libc*.a(shr.o)
 
109
#elif defined(VGP_ppc64_aix5)
 
110
#  define  m_libc_soname     libcZaZdaZLshrZu64ZdoZR // libc*.a(shr_64.o)
 
111
#else
 
112
#  error "Unknown platform"
 
113
#endif
 
114
 
 
115
/* --- Sonames for Linux ELF linkers. --- */
 
116
 
121
117
#define  m_ld_linux_so_2         ldZhlinuxZdsoZd2           // ld-linux.so.2
122
118
#define  m_ld_linux_x86_64_so_2  ldZhlinuxZhx86Zh64ZdsoZd2  // ld-linux-x86-64.so.2
123
119
#define  m_ld64_so_1             ld64ZdsoZd1                // ld64.so.1
139
135
   }
140
136
 
141
137
// Apparently rindex() is the same thing as strrchr()
142
 
STRRCHR(m_libc_so_star,  strrchr)
143
 
STRRCHR(m_libc_so_star,  rindex)
 
138
STRRCHR(m_libc_soname,   strrchr)
 
139
STRRCHR(m_libc_soname,   rindex)
144
140
STRRCHR(m_ld_linux_so_2, rindex)
145
141
   
146
142
 
158
154
   }
159
155
 
160
156
// Apparently index() is the same thing as strchr()
161
 
STRCHR(m_libc_so_star,         strchr)
 
157
STRCHR(m_libc_soname,          strchr)
162
158
STRCHR(m_ld_linux_so_2,        strchr)
163
159
STRCHR(m_ld_linux_x86_64_so_2, strchr)
164
 
STRCHR(m_libc_so_star,         index)
 
160
STRCHR(m_libc_soname,          index)
165
161
STRCHR(m_ld_linux_so_2,        index)
166
162
STRCHR(m_ld_linux_x86_64_so_2, index)
167
163
 
175
171
      while (*dst) dst++; \
176
172
      while (*src) *dst++ = *src++; \
177
173
      *dst = 0; \
178
 
 \
 
174
      \
179
175
      /* This is a bit redundant, I think;  any overlap and the strcat will */ \
180
176
      /* go forever... or until a seg fault occurs. */ \
181
177
      if (is_overlap(dst_orig,  \
182
178
                     src_orig,  \
183
179
                     (Addr)dst-(Addr)dst_orig+1,  \
184
180
                     (Addr)src-(Addr)src_orig+1)) \
185
 
         complain2("strcat", dst_orig, src_orig); \
186
 
 \
 
181
         RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \
 
182
      \
187
183
      return dst_orig; \
188
184
   }
189
185
 
190
 
STRCAT(m_libc_so_star, strcat)
 
186
STRCAT(m_libc_soname, strcat)
191
187
 
192
188
 
193
189
#define STRNCAT(soname, fnname) \
199
195
      const Char* src_orig = src; \
200
196
            Char* dst_orig = dst; \
201
197
      SizeT m = 0; \
202
 
 \
 
198
      \
203
199
      while (*dst) dst++; \
204
200
      while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \
205
201
      *dst = 0;                                       /* always add null   */ \
206
 
 \
 
202
      \
207
203
      /* This checks for overlap after copying, unavoidable without */ \
208
204
      /* pre-counting lengths... should be ok */ \
209
205
      if (is_overlap(dst_orig,  \
210
206
                     src_orig,  \
211
207
                     (Addr)dst-(Addr)dst_orig+1,  \
212
208
                     (Addr)src-(Addr)src_orig+1)) \
213
 
         complain3("strncat", dst_orig, src_orig, n); \
214
 
 \
 
209
         RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \
 
210
      \
215
211
      return dst_orig; \
216
212
   }
217
213
 
218
 
STRNCAT(m_libc_so_star, strncat)
219
 
   
 
214
STRNCAT(m_libc_soname, strncat)
 
215
 
220
216
 
221
217
#define STRNLEN(soname, fnname) \
222
218
   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
227
223
      return i; \
228
224
   }
229
225
 
230
 
STRNLEN(m_libc_so_star, strnlen)
 
226
STRNLEN(m_libc_soname, strnlen)
231
227
   
232
228
 
233
229
// Note that this replacement often doesn't get used because gcc inlines
243
239
      return i; \
244
240
   }
245
241
 
246
 
STRLEN(m_libc_so_star,         strlen)
 
242
STRLEN(m_libc_soname,          strlen)
247
243
STRLEN(m_ld_linux_so_2,        strlen)
248
244
STRLEN(m_ld_linux_x86_64_so_2, strlen)
249
 
   
 
245
 
250
246
 
251
247
#define STRCPY(soname, fnname) \
252
248
   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
254
250
   { \
255
251
      const Char* src_orig = src; \
256
252
            Char* dst_orig = dst; \
257
 
 \
 
253
      \
258
254
      while (*src) *dst++ = *src++; \
259
255
      *dst = 0; \
260
 
 \
 
256
      \
261
257
      /* This checks for overlap after copying, unavoidable without */ \
262
258
      /* pre-counting length... should be ok */ \
263
259
      if (is_overlap(dst_orig,  \
264
260
                     src_orig,  \
265
261
                     (Addr)dst-(Addr)dst_orig+1,  \
266
262
                     (Addr)src-(Addr)src_orig+1)) \
267
 
         complain2("strcpy", dst_orig, src_orig); \
268
 
 \
 
263
         RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \
 
264
      \
269
265
      return dst_orig; \
270
266
   }
271
267
 
272
 
STRCPY(m_libc_so_star, strcpy)
 
268
STRCPY(m_libc_soname, strcpy)
273
269
 
274
270
 
275
271
#define STRNCPY(soname, fnname) \
281
277
      const Char* src_orig = src; \
282
278
            Char* dst_orig = dst; \
283
279
      SizeT m = 0; \
284
 
 \
 
280
      \
285
281
      while (m   < n && *src) { m++; *dst++ = *src++; } \
286
282
      /* Check for overlap after copying; all n bytes of dst are relevant, */ \
287
283
      /* but only m+1 bytes of src if terminator was found */ \
288
284
      if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \
289
 
         complain3("strncpy", dst, src, n); \
 
285
         RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \
290
286
      while (m++ < n) *dst++ = 0;         /* must pad remainder with nulls */ \
291
287
 \
292
288
      return dst_orig; \
293
289
   }
294
290
 
295
 
STRNCPY(m_libc_so_star, strncpy)
 
291
STRNCPY(m_libc_soname, strncpy)
296
292
 
297
293
 
298
294
#define STRNCMP(soname, fnname) \
307
303
         if (*s1 == 0 && *s2 == 0) return 0; \
308
304
         if (*s1 == 0) return -1; \
309
305
         if (*s2 == 0) return 1; \
310
 
 \
 
306
         \
311
307
         if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \
312
308
         if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \
313
 
 \
 
309
         \
314
310
         s1++; s2++; n++; \
315
311
      } \
316
312
   }
317
313
 
318
 
STRNCMP(m_libc_so_star, strncmp)
 
314
STRNCMP(m_libc_soname, strncmp)
319
315
 
320
316
 
321
317
#define STRCMP(soname, fnname) \
338
334
      return 0; \
339
335
   }
340
336
 
341
 
STRCMP(m_libc_so_star,         strcmp)
 
337
STRCMP(m_libc_soname,          strcmp)
342
338
STRCMP(m_ld_linux_x86_64_so_2, strcmp)
343
339
STRCMP(m_ld64_so_1,            strcmp)
344
340
 
355
351
      return NULL; \
356
352
   }
357
353
 
358
 
MEMCHR(m_libc_so_star, memchr)
 
354
MEMCHR(m_libc_soname, memchr)
359
355
 
360
356
 
361
357
#define MEMCPY(soname, fnname) \
366
362
   { \
367
363
      register char *d; \
368
364
      register char *s; \
369
 
 \
 
365
      \
370
366
      if (len == 0) \
371
367
         return dst; \
372
 
 \
 
368
      \
373
369
      if (is_overlap(dst, src, len, len)) \
374
 
         complain3("memcpy", dst, src, len); \
375
 
 \
 
370
         RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \
 
371
      \
376
372
      if ( dst > src ) { \
377
373
         d = (char *)dst + len - 1; \
378
374
         s = (char *)src + len - 1; \
403
399
      return dst; \
404
400
   }
405
401
 
406
 
MEMCPY(m_libc_so_star, memcpy)
407
 
MEMCPY(m_ld_so_1,      memcpy) /* ld.so.1 */
408
 
   
 
402
MEMCPY(m_libc_soname, memcpy)
 
403
MEMCPY(m_ld_so_1,     memcpy) /* ld.so.1 */
 
404
MEMCPY(m_ld64_so_1,   memcpy) /* ld64.so.1 */
 
405
/* icc9 blats these around all over the place.  Not only in the main
 
406
   executable but various .so's.  They are highly tuned and read
 
407
   memory beyond the source boundary (although work correctly and
 
408
   never go across page boundaries), so give errors when run natively,
 
409
   at least for misaligned source arg.  Just intercepting in the exe
 
410
   only until we understand more about the problem.  See
 
411
   http://bugs.kde.org/show_bug.cgi?id=139776
 
412
 */
 
413
MEMCPY(NONE, _intel_fast_memcpy)
 
414
 
409
415
 
410
416
#define MEMCMP(soname, fnname) \
411
417
   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
418
424
      unsigned char b0; \
419
425
      unsigned char* s1 = (unsigned char*)s1V; \
420
426
      unsigned char* s2 = (unsigned char*)s2V; \
421
 
 \
 
427
      \
422
428
      while (n != 0) { \
423
429
         a0 = s1[0]; \
424
430
         b0 = s2[0]; \
432
438
      return 0; \
433
439
   }
434
440
 
435
 
MEMCMP(m_libc_so_star, memcmp)
436
 
MEMCMP(m_libc_so_star, bcmp)
 
441
MEMCMP(m_libc_soname, memcmp)
 
442
MEMCMP(m_libc_soname, bcmp)
 
443
MEMCMP(m_ld_so_1, bcmp)
437
444
 
438
445
 
439
446
/* Copy SRC to DEST, returning the address of the terminating '\0' in
444
451
   { \
445
452
      const Char* src_orig = src; \
446
453
            Char* dst_orig = dst; \
447
 
 \
 
454
      \
448
455
      while (*src) *dst++ = *src++; \
449
456
      *dst = 0; \
450
 
 \
 
457
      \
451
458
      /* This checks for overlap after copying, unavoidable without */ \
452
459
      /* pre-counting length... should be ok */ \
453
460
      if (is_overlap(dst_orig,  \
454
461
                     src_orig,  \
455
462
                     (Addr)dst-(Addr)dst_orig+1,  \
456
463
                     (Addr)src-(Addr)src_orig+1)) \
457
 
         complain2("stpcpy", dst_orig, src_orig); \
458
 
 \
 
464
         RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \
 
465
      \
459
466
      return dst; \
460
467
   }
461
468
 
462
 
STPCPY(m_libc_so_star,         stpcpy)
 
469
STPCPY(m_libc_soname,         stpcpy)
463
470
STPCPY(m_ld_linux_so_2,        stpcpy)
464
471
STPCPY(m_ld_linux_x86_64_so_2, stpcpy)
465
472
   
469
476
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname)(void *s, Int c, SizeT n) \
470
477
   { \
471
478
      unsigned char *cp = s; \
472
 
 \
473
 
      while(n--) \
 
479
      while (n >= 4) { \
 
480
         cp[0] = c; \
 
481
         cp[1] = c; \
 
482
         cp[2] = c; \
 
483
         cp[3] = c; \
 
484
         cp += 4; \
 
485
         n -= 4; \
 
486
      } \
 
487
      while (n--) { \
474
488
         *cp++ = c; \
475
 
 \
 
489
      } \
476
490
      return s; \
477
491
   }
478
492
 
479
 
MEMSET(m_libc_so_star, memset)
 
493
MEMSET(m_libc_soname, memset)
480
494
 
481
495
 
482
496
#define MEMMOVE(soname, fnname) \
500
514
      return dst; \
501
515
   }
502
516
 
503
 
MEMMOVE(m_libc_so_star, memmove)
 
517
MEMMOVE(m_libc_soname, memmove)
 
518
 
 
519
 
 
520
/* glibc 2.5 variant of memmove which checks the dest is big enough.
 
521
   There is no specific part of glibc that this is copied from. */
 
522
#define GLIBC25___MEMMOVE_CHK(soname, fnname) \
 
523
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
524
            (void *dstV, const void *srcV, SizeT n, SizeT destlen); \
 
525
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
526
            (void *dstV, const void *srcV, SizeT n, SizeT destlen) \
 
527
   { \
 
528
      extern void _exit(int status); \
 
529
      SizeT i; \
 
530
      Char* dst = (Char*)dstV; \
 
531
      Char* src = (Char*)srcV; \
 
532
      if (destlen < n) \
 
533
         goto badness; \
 
534
      if (dst < src) { \
 
535
         for (i = 0; i < n; i++) \
 
536
            dst[i] = src[i]; \
 
537
      } \
 
538
      else  \
 
539
      if (dst > src) { \
 
540
         for (i = 0; i < n; i++) \
 
541
            dst[n-i-1] = src[n-i-1]; \
 
542
      } \
 
543
      return dst; \
 
544
     badness: \
 
545
      VALGRIND_PRINTF_BACKTRACE( \
 
546
         "*** memmove_chk: buffer overflow detected ***: " \
 
547
         "program terminated"); \
 
548
     _exit(127); \
 
549
     /*NOTREACHED*/ \
 
550
     return NULL; \
 
551
   }
 
552
 
 
553
GLIBC25___MEMMOVE_CHK(m_libc_soname, __memmove_chk)
504
554
 
505
555
 
506
556
/* Find the first occurrence of C in S or the final NUL byte.  */
517
567
      } \
518
568
   }
519
569
 
520
 
GLIBC232_STRCHRNUL(m_libc_so_star, strchrnul)
 
570
GLIBC232_STRCHRNUL(m_libc_soname, strchrnul)
521
571
 
522
572
 
523
573
/* Find the first occurrence of C in S.  */
533
583
      } \
534
584
   }
535
585
 
536
 
GLIBC232_RAWMEMCHR(m_libc_so_star, rawmemchr)
537
 
 
 
586
GLIBC232_RAWMEMCHR(m_libc_soname, rawmemchr)
 
587
 
 
588
 
 
589
/* glibc variant of strcpy that checks the dest is big enough.
 
590
   Copied from glibc-2.5/debug/test-strcpy_chk.c. */
 
591
#define GLIBC25___STRCPY_CHK(soname,fnname) \
 
592
   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
593
                               (char* dst, const char* src, SizeT len); \
 
594
   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
595
                               (char* dst, const char* src, SizeT len) \
 
596
   { \
 
597
      extern void _exit(int status); \
 
598
      char* ret = dst; \
 
599
      if (! len) \
 
600
         goto badness; \
 
601
      while ((*dst++ = *src++) != '\0') \
 
602
         if (--len == 0) \
 
603
            goto badness; \
 
604
      return ret; \
 
605
     badness: \
 
606
      VALGRIND_PRINTF_BACKTRACE( \
 
607
         "*** strcpy_chk: buffer overflow detected ***: " \
 
608
         "program terminated"); \
 
609
     _exit(127); \
 
610
     /*NOTREACHED*/ \
 
611
     return NULL; \
 
612
   }
 
613
 
 
614
GLIBC25___STRCPY_CHK(m_libc_soname, __strcpy_chk)
 
615
 
 
616
 
 
617
/* glibc variant of stpcpy that checks the dest is big enough.
 
618
   Copied from glibc-2.5/debug/test-stpcpy_chk.c. */
 
619
#define GLIBC25___STPCPY_CHK(soname,fnname) \
 
620
   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
621
                               (char* dst, const char* src, SizeT len); \
 
622
   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
623
                               (char* dst, const char* src, SizeT len) \
 
624
   { \
 
625
      extern void _exit(int status); \
 
626
      if (! len) \
 
627
         goto badness; \
 
628
      while ((*dst++ = *src++) != '\0') \
 
629
         if (--len == 0) \
 
630
            goto badness; \
 
631
      return dst - 1; \
 
632
     badness: \
 
633
      VALGRIND_PRINTF_BACKTRACE( \
 
634
         "*** stpcpy_chk: buffer overflow detected ***: " \
 
635
         "program terminated"); \
 
636
     _exit(127); \
 
637
     /*NOTREACHED*/ \
 
638
     return NULL; \
 
639
   }
 
640
 
 
641
GLIBC25___STPCPY_CHK(m_libc_soname, __stpcpy_chk)
 
642
 
 
643
 
 
644
/* mempcpy */
 
645
#define GLIBC25_MEMPCPY(soname, fnname) \
 
646
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
647
            ( void *dst, const void *src, SizeT len ); \
 
648
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
649
            ( void *dst, const void *src, SizeT len ) \
 
650
   { \
 
651
      register char *d; \
 
652
      register char *s; \
 
653
      SizeT len_saved = len; \
 
654
      \
 
655
      if (len == 0) \
 
656
         return dst; \
 
657
      \
 
658
      if (is_overlap(dst, src, len, len)) \
 
659
         RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \
 
660
      \
 
661
      if ( dst > src ) { \
 
662
         d = (char *)dst + len - 1; \
 
663
         s = (char *)src + len - 1; \
 
664
         while ( len-- ) { \
 
665
            *d-- = *s--; \
 
666
         } \
 
667
      } else if ( dst < src ) { \
 
668
         d = (char *)dst; \
 
669
         s = (char *)src; \
 
670
         while ( len-- ) { \
 
671
            *d++ = *s++; \
 
672
         } \
 
673
      } \
 
674
      return (void*)( ((char*)dst) + len_saved ); \
 
675
   }
 
676
 
 
677
GLIBC25_MEMPCPY(m_libc_soname, mempcpy)
 
678
GLIBC25_MEMPCPY(m_ld_so_1,     mempcpy) /* ld.so.1 */
 
679
 
 
680
 
 
681
#define GLIBC26___MEMCPY_CHK(soname, fnname) \
 
682
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
683
            (void* dst, const void* src, SizeT len, SizeT dstlen ); \
 
684
   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
 
685
            (void* dst, const void* src, SizeT len, SizeT dstlen ) \
 
686
   { \
 
687
      extern void _exit(int status); \
 
688
      register char *d; \
 
689
      register char *s; \
 
690
      \
 
691
      if (dstlen < len) goto badness; \
 
692
      \
 
693
      if (len == 0) \
 
694
         return dst; \
 
695
      \
 
696
      if (is_overlap(dst, src, len, len)) \
 
697
         RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \
 
698
      \
 
699
      if ( dst > src ) { \
 
700
         d = (char *)dst + len - 1; \
 
701
         s = (char *)src + len - 1; \
 
702
         while ( len-- ) { \
 
703
            *d-- = *s--; \
 
704
         } \
 
705
      } else if ( dst < src ) { \
 
706
         d = (char *)dst; \
 
707
         s = (char *)src; \
 
708
         while ( len-- ) { \
 
709
            *d++ = *s++; \
 
710
         } \
 
711
      } \
 
712
      return dst; \
 
713
     badness: \
 
714
      VALGRIND_PRINTF_BACKTRACE( \
 
715
         "*** memcpy_chk: buffer overflow detected ***: " \
 
716
         "program terminated"); \
 
717
     _exit(127); \
 
718
     /*NOTREACHED*/ \
 
719
     return NULL; \
 
720
   }
 
721
 
 
722
GLIBC26___MEMCPY_CHK(m_libc_soname, __memcpy_chk)
 
723
 
 
724
 
 
725
/*------------------------------------------------------------*/
 
726
/*--- Improve definedness checking of process environment  ---*/
 
727
/*------------------------------------------------------------*/
 
728
 
 
729
#if defined(VGO_linux)
 
730
 
 
731
/* putenv */
 
732
int VG_WRAP_FUNCTION_ZU(m_libc_soname, putenv) (char* string);
 
733
int VG_WRAP_FUNCTION_ZU(m_libc_soname, putenv) (char* string)
 
734
{
 
735
    OrigFn fn;
 
736
    Word result;
 
737
    const char* p = string;
 
738
    VALGRIND_GET_ORIG_FN(fn);
 
739
    /* Now by walking over the string we magically produce
 
740
       traces when hitting undefined memory. */
 
741
    if (p)
 
742
        while (*p++)
 
743
            ;
 
744
    CALL_FN_W_W(result, fn, string);
 
745
    return result;
 
746
}
 
747
 
 
748
/* unsetenv */
 
749
int VG_WRAP_FUNCTION_ZU(m_libc_soname, unsetenv) (const char* name);
 
750
int VG_WRAP_FUNCTION_ZU(m_libc_soname, unsetenv) (const char* name)
 
751
{
 
752
    OrigFn fn;
 
753
    Word result;
 
754
    const char* p = name;
 
755
    VALGRIND_GET_ORIG_FN(fn);
 
756
    /* Now by walking over the string we magically produce
 
757
       traces when hitting undefined memory. */
 
758
    if (p)
 
759
        while (*p++)
 
760
            ;
 
761
    CALL_FN_W_W(result, fn, name);
 
762
    return result;
 
763
}
 
764
 
 
765
/* setenv */
 
766
int VG_WRAP_FUNCTION_ZU(m_libc_soname, setenv)
 
767
    (const char* name, const char* value, int overwrite);
 
768
int VG_WRAP_FUNCTION_ZU(m_libc_soname, setenv)
 
769
    (const char* name, const char* value, int overwrite)
 
770
{
 
771
    OrigFn fn;
 
772
    Word result;
 
773
    const char* p;
 
774
    VALGRIND_GET_ORIG_FN(fn);
 
775
    /* Now by walking over the string we magically produce
 
776
       traces when hitting undefined memory. */
 
777
    if (name)
 
778
        for (p = name; *p; p++)
 
779
            ;
 
780
    if (value)
 
781
        for (p = value; *p; p++)
 
782
            ;
 
783
    VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite);
 
784
    CALL_FN_W_WWW(result, fn, name, value, overwrite);
 
785
    return result;
 
786
}
 
787
 
 
788
#endif /* defined(VGO_linux) */
 
789
 
 
790
 
 
791
/*------------------------------------------------------------*/
 
792
/*--- AIX stuff only after this point                      ---*/
 
793
/*------------------------------------------------------------*/
 
794
 
 
795
/* Generate replacements for strcat, strncat, strcpy, strncpy, strcmp
 
796
   in the given soname. */
 
797
#define Str5FNs(_soname)       \
 
798
    STRCAT(_soname, strcat)    \
 
799
   STRNCAT(_soname, strncat)   \
 
800
    STRCPY(_soname, strcpy)    \
 
801
   STRNCPY(_soname, strncpy)   \
 
802
    STRCMP(_soname, strcmp)
 
803
 
 
804
#if defined(VGP_ppc32_aix5)
 
805
Str5FNs(NONE)                             /* in main exe */
 
806
Str5FNs(libCZdaZLshrcoreZdoZR)            /* libC.a(shrcore.o) */
 
807
Str5FNs(libX11ZdaZLshr4ZdoZR)             /* libX11.a(shr4.o) */
 
808
Str5FNs(libXmZdaZLshrZaZdoZR)             /* libXm.a(shr*.o) */
 
809
Str5FNs(libXtZdaZLshr4ZdoZR)              /* libXt.a(shr4.o) */
 
810
Str5FNs(libppeZurZdaZLdynamicZdoZR)       /* libppe_r.a(dynamic.o) */
 
811
Str5FNs(libodmZdaZLshrZdoZR)              /* libodm.a(shr.o) */
 
812
Str5FNs(libmpiZurZdaZLmpicoreZurZdoZR)    /* libmpi_r.a(mpicore_r.o) */
 
813
Str5FNs(libmpiZurZdaZLmpipoeZurZdoZR)     /* libmpi_r.a(mpipoe_r.o) */
 
814
Str5FNs(libmpiZurZdaZLmpciZurZdoZR)       /* libmpi_r.a(mpci_r.o) */
 
815
Str5FNs(libslurmZdso)                     /* libslurm.so */
 
816
Str5FNs(libglibZdso)                      /* libglib.so */
 
817
Str5FNs(libIMZdaZLshrZdoZR)               /* libIM.a(shr.o) */
 
818
Str5FNs(libiconvZdaZLshr4ZdoZR)           /* libiconv.a(shr4.o) */
 
819
Str5FNs(libGLZdaZLshrZdoZR)               /* libGL.a(shr.o) */
 
820
Str5FNs(libgdkZdso)                       /* libgdk.so */
 
821
Str5FNs(libcursesZdaZLshr42ZdoZR)         /* libcurses.a(shr42.o) */
 
822
Str5FNs(libqtZda)                         /* libqt.a */
 
823
Str5FNs(ZaZLlibglibZhZaZdsoZaZR)          /* *(libglib-*.so*) */
 
824
Str5FNs(ZaZLlibfontconfigZdsoZaZR)        /* *(libfontconfig.so*) */
 
825
Str5FNs(libQtZaa)                         /* libQt*.a */
 
826
#endif
 
827
#if defined(VGP_ppc64_aix5)
 
828
Str5FNs(NONE)                             /* in main exe */
 
829
Str5FNs(libX11ZdaZLshrZu64ZdoZR)          /* libX11.a(shr_64.o) */
 
830
Str5FNs(libiconvZdaZLshr4Zu64ZdoZR)       /* libiconv.a(shr4_64.o) */
 
831
Str5FNs(libGLZdaZLshrZu64ZdoZR)           /* libGL.a(shr_64.o) */
 
832
Str5FNs(libppeZurZdaZLdynamic64ZdoZR)     /* libppe_r.a(dynamic64.o) */
 
833
Str5FNs(libodmZdaZLshrZu64ZdoZR)          /* libodm.a(shr_64.o) */
 
834
Str5FNs(libmpiZurZdaZLmpicore64ZurZdoZR)  /* libmpi_r.a(mpicore64_r.o) */
 
835
Str5FNs(libmpiZurZdaZLmpipoe64ZurZdoZR)   /* libmpi_r.a(mpipoe64_r.o) */
 
836
Str5FNs(libCZdaZLshrcoreZu64ZdoZR)        /* libC.a(shrcore_64.o) */
 
837
Str5FNs(libmpiZurZdaZLmpci64ZurZdoZR)     /* libmpi_r.a(mpci64_r.o) */
 
838
Str5FNs(libqtZda)                         /* libqt.a */
 
839
Str5FNs(ZaZLlibglibZhZaZdsoZaZR)          /* *(libglib-*.so*) */
 
840
Str5FNs(ZaZLlibfontconfigZdsoZaZR)        /* *(libfontconfig.so*) */
 
841
Str5FNs(libQtZaa)                         /* libQt*.a */
 
842
#endif
 
843
 
 
844
 
 
845
/* AIX's libm contains a sqrt implementation which does a nasty thing:
 
846
   it loads the initial estimate of the root into a FP register, but
 
847
   only the upper half of the number is initialised data.  Hence the
 
848
   least significant 32 mantissa bits are undefined, and it then uses
 
849
   Newton-Raphson iteration to compute the final, defined result.
 
850
   This fools memcheck completely; the only solution I can think of is
 
851
   provide our own substitute.  The _FAST variant is almost right
 
852
   except the result is not correctly rounded.  The _EXACT variant,
 
853
   which is selected by default, is always right; but it's also pretty
 
854
   darn slow. */
 
855
 
 
856
#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
 
857
#define SQRT_FAST(soname, fnname) \
 
858
   double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
 
859
   double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
 
860
   { \
 
861
      static UInt T1[32] =  \
 
862
         { 0,       1024,   3062,   5746,   9193,  13348, \
 
863
           18162,  23592,  29598,  36145,  43202,  50740, \
 
864
           58733,  67158,  75992,  85215,  83599,  71378, \
 
865
           60428,  50647,  41945,  34246,  27478,  21581, \
 
866
           16499,  12183,   8588,   5674,   3403,   1742, \
 
867
           661,    130 }; \
 
868
      UInt x0, x1, sign, expo, mant0, bIGENDIAN = 1; \
 
869
      union { UInt w[2]; double d; } u; \
 
870
      u.d   = x; \
 
871
      x0    = u.w[1 - bIGENDIAN]; /* high half */ \
 
872
      x1    = u.w[bIGENDIAN];  /* low half */ \
 
873
      sign  = x0 >> 31; \
 
874
      expo  = (x0 >> 20) & 0x7FF; \
 
875
      mant0 = x0 & 0xFFFFF; \
 
876
      if ( (sign == 0 && expo >= 1 && expo <= 0x7FE) /* +normal */ \
 
877
           || (sign == 0 && expo == 0  \
 
878
                         && (mant0 | x1) > 0) /* +denorm */) { \
 
879
         /* common case; do Newton-Raphson */ \
 
880
         /* technically k should be signed int32, but since we're \
 
881
            always entering here with x > 0, doesn't matter that it's \
 
882
            unsigned. */ \
 
883
         double y; \
 
884
         UInt k = (x0>>1) + 0x1ff80000; \
 
885
         u.w[1 - bIGENDIAN] = k - T1[31&(k>>15)]; \
 
886
         u.w[bIGENDIAN] = 0; \
 
887
         y = u.d; \
 
888
         y = (y+x/y)/2.0 ; \
 
889
         y = (y+x/y)/2.0 ; \
 
890
         y = y-(y-x/y)/2.0 ; \
 
891
         return y; \
 
892
      } \
 
893
      if ( (sign == 1 && expo >= 1 && expo <= 0x7FE) /* -normal */ \
 
894
           || (sign == 1 && expo == 0  \
 
895
                         && (mant0 | x1) > 0) /* -denorm */) { \
 
896
         u.w[1 - bIGENDIAN] = 0xFFF00000; \
 
897
         u.w[bIGENDIAN] = 0x1; \
 
898
         return u.d; /* -Inf -> NaN */ \
 
899
      } \
 
900
      if ((expo | mant0 | x1) == 0) \
 
901
         return x; /* +/-zero -> self */ \
 
902
      if (expo == 0x7FF && (mant0 | x1) == 0) { \
 
903
         if (sign == 0) \
 
904
            return x; /* +Inf -> self */ \
 
905
         u.w[1 - bIGENDIAN] = 0xFFF00000; \
 
906
         u.w[bIGENDIAN] = 0x1; \
 
907
         return u.d; /* -Inf -> NaN */ \
 
908
      } \
 
909
      /* must be +/- NaN */ \
 
910
      return x; /* +/-NaN -> self */ \
 
911
   }
 
912
 
 
913
#define SQRT_EXACT(soname, fnname) \
 
914
   /* \
 
915
    * ==================================================== \
 
916
    * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. \
 
917
    * \
 
918
    * Developed at SunPro, a Sun Microsystems, Inc. business. \
 
919
    * Permission to use, copy, modify, and distribute this \
 
920
    * software is freely granted, provided that this notice \
 
921
    * is preserved. \
 
922
    * ==================================================== \
 
923
    */ \
 
924
   /* \
 
925
    * Return correctly rounded sqrt. \
 
926
    *           ------------------------------------------ \
 
927
    *           |  Use the hardware sqrt if you have one | \
 
928
    *           ------------------------------------------ \
 
929
    * Method: \
 
930
    *   Bit by bit method using integer arithmetic. (Slow, but portable) \
 
931
    *   1. Normalization \
 
932
    *      Scale x to y in [1,4) with even powers of 2: \
 
933
    *      find an integer k such that  1 <= (y=x*2^(2k)) < 4, then \
 
934
    *              sqrt(x) = 2^k * sqrt(y) \
 
935
    *   2. Bit by bit computation \
 
936
    *      Let q  = sqrt(y) truncated to i bit after binary point (q = 1), \
 
937
    *           i                                                   0 \
 
938
    *                                     i+1         2 \
 
939
    *          s  = 2*q , and      y  =  2   * ( y - q  ).         (1) \
 
940
    *           i      i            i                 i \
 
941
    * \
 
942
    *      To compute q    from q , one checks whether \
 
943
    *                  i+1       i \
 
944
    * \
 
945
    *                            -(i+1) 2 \
 
946
    *                      (q + 2      ) <= y.                     (2) \
 
947
    *                        i \
 
948
    *                                                            -(i+1) \
 
949
    *      If (2) is false, then q   = q ; otherwise q   = q  + 2      . \
 
950
    *                             i+1   i             i+1   i \
 
951
    * \
 
952
    *      With some algebric manipulation, it is not difficult to see \
 
953
    *      that (2) is equivalent to \
 
954
    *                             -(i+1) \
 
955
    *                      s  +  2       <= y                      (3) \
 
956
    *                       i                i \
 
957
    * \
 
958
    *      The advantage of (3) is that s  and y  can be computed by \
 
959
    *                                    i      i \
 
960
    *      the following recurrence formula: \
 
961
    *          if (3) is false \
 
962
    * \
 
963
    *          s     =  s  ,       y    = y   ;                    (4) \
 
964
    *           i+1      i          i+1    i \
 
965
    * \
 
966
    *          otherwise, \
 
967
    *                         -i                     -(i+1) \
 
968
    *          s     =  s  + 2  ,  y    = y  -  s  - 2             (5) \
 
969
    *           i+1      i          i+1    i     i \
 
970
    * \
 
971
    * \
 
972
    *      One may easily use induction to prove (4) and (5). \
 
973
    *      Note. Since the left hand side of (3) contain only i+2 bits, \
 
974
    *            it does not necessary to do a full (53-bit) comparison \
 
975
    *            in (3). \
 
976
    *   3. Final rounding \
 
977
    *      After generating the 53 bits result, we compute one more bit. \
 
978
    *      Together with the remainder, we can decide whether the \
 
979
    *      result is exact, bigger than 1/2ulp, or less than 1/2ulp \
 
980
    *      (it will never equal to 1/2ulp). \
 
981
    *      The rounding mode can be detected by checking whether \
 
982
    *      huge + tiny is equal to huge, and whether huge - tiny is \
 
983
    *      equal to huge for some floating point number "huge" and "tiny". \
 
984
    * \
 
985
    * Special cases: \
 
986
    *      sqrt(+-0) = +-0         ... exact \
 
987
    *      sqrt(inf) = inf \
 
988
    *      sqrt(-ve) = NaN         ... with invalid signal \
 
989
    *      sqrt(NaN) = NaN         ... with invalid signal for signaling NaN \
 
990
    * \
 
991
    */ \
 
992
   double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
 
993
   double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
 
994
   {  \
 
995
      const Int    bIGENDIAN = 1; \
 
996
      const double one = 1.0, tiny=1.0e-300; \
 
997
      double z; \
 
998
      Int sign = (Int)0x80000000; \
 
999
      Int ix0,s0,q,m,t,i; \
 
1000
      UInt r,t1,s1,ix1,q1; \
 
1001
      union { UInt w[2]; double d; } u; \
 
1002
      u.d = x; \
 
1003
      ix0 = u.w[1-bIGENDIAN]; \
 
1004
      ix1 = u.w[bIGENDIAN];    \
 
1005
      \
 
1006
      /* take care of Inf and NaN */ \
 
1007
      if((ix0&0x7ff00000)==0x7ff00000) { \
 
1008
         return x*x+x;               /* sqrt(NaN)=NaN, sqrt(+inf)=+inf \
 
1009
                                        sqrt(-inf)=sNaN */ \
 
1010
      } \
 
1011
      /* take care of zero */ \
 
1012
      if(ix0<=0) { \
 
1013
         if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ \
 
1014
         else if(ix0<0) \
 
1015
              return (x-x)/(x-x);             /* sqrt(-ve) = sNaN */ \
 
1016
      } \
 
1017
      /* normalize x */ \
 
1018
      m = (ix0>>20); \
 
1019
      if(m==0) {                              /* subnormal x */ \
 
1020
         while(ix0==0) { \
 
1021
            m -= 21; \
 
1022
            ix0 |= (ix1>>11); ix1 <<= 21; \
 
1023
         } \
 
1024
         for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; \
 
1025
         m -= i-1; \
 
1026
         ix0 |= (ix1>>(32-i)); \
 
1027
         ix1 <<= i; \
 
1028
      } \
 
1029
      m -= 1023;      /* unbias exponent */ \
 
1030
      ix0 = (ix0&0x000fffff)|0x00100000; \
 
1031
      if(m&1){        /* odd m, double x to make it even */ \
 
1032
         ix0 += ix0 + ((ix1&sign)>>31); \
 
1033
         ix1 += ix1; \
 
1034
      } \
 
1035
      m >>= 1;        /* m = [m/2] */ \
 
1036
      /* generate sqrt(x) bit by bit */ \
 
1037
      ix0 += ix0 + ((ix1&sign)>>31); \
 
1038
      ix1 += ix1; \
 
1039
      q = q1 = s0 = s1 = 0;   /* [q,q1] = sqrt(x) */ \
 
1040
      r = 0x00200000;         /* r = moving bit from right to left */ \
 
1041
      while(r!=0) { \
 
1042
         t = s0+r; \
 
1043
         if(t<=ix0) { \
 
1044
            s0   = t+r; \
 
1045
            ix0 -= t; \
 
1046
            q   += r; \
 
1047
         } \
 
1048
         ix0 += ix0 + ((ix1&sign)>>31); \
 
1049
         ix1 += ix1; \
 
1050
         r>>=1; \
 
1051
      } \
 
1052
      r = sign; \
 
1053
      while(r!=0) { \
 
1054
         t1 = s1+r; \
 
1055
         t  = s0; \
 
1056
         if((t<ix0)||((t==ix0)&&(t1<=ix1))) { \
 
1057
            s1  = t1+r; \
 
1058
            if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; \
 
1059
            ix0 -= t; \
 
1060
            if (ix1 < t1) ix0 -= 1; \
 
1061
            ix1 -= t1; \
 
1062
            q1  += r; \
 
1063
         } \
 
1064
         ix0 += ix0 + ((ix1&sign)>>31); \
 
1065
         ix1 += ix1; \
 
1066
         r>>=1; \
 
1067
      } \
 
1068
      /* use floating add to find out rounding direction */ \
 
1069
      if((ix0|ix1)!=0) { \
 
1070
         z = one-tiny; /* trigger inexact flag */ \
 
1071
         if (z>=one) { \
 
1072
            z = one+tiny; \
 
1073
            if (q1==(UInt)0xffffffff) { q1=0; q += 1;} \
 
1074
            else if (z>one) { \
 
1075
                    if (q1==(UInt)0xfffffffe) q+=1; \
 
1076
                    q1+=2; \
 
1077
                 } else \
 
1078
                    q1 += (q1&1); \
 
1079
         } \
 
1080
      } \
 
1081
      ix0 = (q>>1)+0x3fe00000; \
 
1082
      ix1 = q1>>1; \
 
1083
      if ((q&1)==1) ix1 |= sign; \
 
1084
      ix0 += (m <<20); \
 
1085
      ix0 = u.w[1-bIGENDIAN] = ix0; \
 
1086
      ix1 = u.w[bIGENDIAN] = ix1;    \
 
1087
      z = u.d; \
 
1088
      return z; \
 
1089
   }
 
1090
 
 
1091
#if 0
 
1092
SQRT_FAST(NONE, sqrt)  /* xlC generates these */
 
1093
SQRT_FAST(NONE, _sqrt) /* xlf generates these */
 
1094
#else
 
1095
SQRT_EXACT(NONE, sqrt)  /* xlC generates these */
 
1096
SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
 
1097
#endif
 
1098
 
 
1099
#endif /* defined(VGP_ppc32_aix5) */
538
1100
 
539
1101
/*--------------------------------------------------------------------*/
540
1102
/*--- end                                                          ---*/