blob: fec258af74b86c02d256b0a6fbda6e59d7fa10aa [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Reimplementation of some C library stuff, to avoid depending ---*/
4/*--- on libc.so. ---*/
5/*--- vg_mylibc.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
9 This file is part of Valgrind, an x86 protected-mode emulator
10 designed for debugging and profiling binaries on x86-Unixes.
11
12 Copyright (C) 2000-2002 Julian Seward
13 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file LICENSE.
31*/
32
33#include "vg_include.h"
34
35
36
37/* ---------------------------------------------------------------------
38 Really Actually DO system calls.
39 ------------------------------------------------------------------ */
40
41/* Ripped off from /usr/include/asm/unistd.h. */
42
43static
44UInt vg_do_syscall0 ( UInt syscallno )
45{
46 UInt __res;
47 __asm__ volatile ("int $0x80"
48 : "=a" (__res)
49 : "0" (syscallno) );
50 return __res;
51}
52
53
54static
55UInt vg_do_syscall1 ( UInt syscallno, UInt arg1 )
56{
57 UInt __res;
58 __asm__ volatile ("int $0x80"
59 : "=a" (__res)
60 : "0" (syscallno),
61 "b" (arg1) );
62 return __res;
63}
64
65
66static
67UInt vg_do_syscall2 ( UInt syscallno,
68 UInt arg1, UInt arg2 )
69{
70 UInt __res;
71 __asm__ volatile ("int $0x80"
72 : "=a" (__res)
73 : "0" (syscallno),
74 "b" (arg1),
75 "c" (arg2) );
76 return __res;
77}
78
79
80static
81UInt vg_do_syscall3 ( UInt syscallno,
82 UInt arg1, UInt arg2, UInt arg3 )
83{
84 UInt __res;
85 __asm__ volatile ("int $0x80"
86 : "=a" (__res)
87 : "0" (syscallno),
88 "b" (arg1),
89 "c" (arg2),
90 "d" (arg3) );
91 return __res;
92}
93
94
95static
96UInt vg_do_syscall4 ( UInt syscallno,
97 UInt arg1, UInt arg2, UInt arg3, UInt arg4 )
98{
99 UInt __res;
100 __asm__ volatile ("int $0x80"
101 : "=a" (__res)
102 : "0" (syscallno),
103 "b" (arg1),
104 "c" (arg2),
105 "d" (arg3),
106 "S" (arg4) );
107 return __res;
108}
109
110
111#if 0
112static
113UInt vg_do_syscall5 ( UInt syscallno,
114 UInt arg1, UInt arg2, UInt arg3, UInt arg4,
115 UInt arg5 )
116{
117 UInt __res;
118 __asm__ volatile ("int $0x80"
119 : "=a" (__res)
120 : "0" (syscallno),
121 "b" (arg1),
122 "c" (arg2),
123 "d" (arg3),
124 "S" (arg4),
125 "D" (arg5) );
126 return __res;
127}
128#endif
129
130/* ---------------------------------------------------------------------
131 Wrappers around system calls, and other stuff, to do with signals.
132 ------------------------------------------------------------------ */
133
134/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
135 success and -1 on error.
136*/
137Int VG_(ksigfillset)( vki_ksigset_t* set )
138{
139 Int i;
140 if (set == NULL)
141 return -1;
142 for (i = 0; i < VKI_KNSIG_WORDS; i++)
143 set->ws[i] = 0xFFFFFFFF;
144 return 0;
145}
146
147Int VG_(ksigemptyset)( vki_ksigset_t* set )
148{
149 Int i;
150 if (set == NULL)
151 return -1;
152 for (i = 0; i < VKI_KNSIG_WORDS; i++)
153 set->ws[i] = 0x0;
154 return 0;
155}
156
157Int VG_(ksigaddset)( vki_ksigset_t* set, Int signum )
158{
159 if (set == NULL)
160 return -1;
161 if (signum < 1 && signum > VKI_KNSIG)
162 return -1;
163 signum--;
164 set->ws[signum / VKI_KNSIG_BPW] |= (1 << (signum % VKI_KNSIG_BPW));
165 return 0;
166}
167
168Int VG_(ksigismember) ( vki_ksigset_t* set, Int signum )
169{
170 if (set == NULL)
171 return -1;
172 if (signum < 1 && signum > VKI_KNSIG)
173 return -1;
174 signum--;
175 if (1 & ((set->ws[signum / VKI_KNSIG_BPW]) >> (signum % VKI_KNSIG_BPW)))
176 return 1;
177 else
178 return 0;
179}
180
181
182/* The functions sigaction, sigprocmask, sigpending and sigsuspend
183 return 0 on success and -1 on error.
184*/
185Int VG_(ksigprocmask)( Int how,
186 const vki_ksigset_t* set,
187 vki_ksigset_t* oldset)
188{
189 Int res
190 = vg_do_syscall4(__NR_rt_sigprocmask,
191 how, (UInt)set, (UInt)oldset,
192 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
193 return VG_(is_kerror)(res) ? -1 : 0;
194}
195
196
197Int VG_(ksigaction) ( Int signum,
198 const vki_ksigaction* act,
199 vki_ksigaction* oldact)
200{
201 Int res
202 = vg_do_syscall4(__NR_rt_sigaction,
203 signum, (UInt)act, (UInt)oldact,
204 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
205 return VG_(is_kerror)(res) ? -1 : 0;
206}
207
208
209Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss )
210{
211 Int res
212 = vg_do_syscall2(__NR_sigaltstack, (UInt)ss, (UInt)oss);
213 return VG_(is_kerror)(res) ? -1 : 0;
214}
215
216
217Int VG_(ksignal)(Int signum, void (*sighandler)(Int))
218{
219 Int res;
220 vki_ksigaction sa;
221 sa.ksa_handler = sighandler;
222 sa.ksa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
223 sa.ksa_restorer = NULL;
224 res = VG_(ksigemptyset)( &sa.ksa_mask );
225 vg_assert(res == 0);
226 res = vg_do_syscall4(__NR_rt_sigaction,
227 signum, (UInt)(&sa), (UInt)NULL,
228 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
229 return VG_(is_kerror)(res) ? -1 : 0;
230}
231
232
233/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000234 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000235 ------------------------------------------------------------------ */
236
237/* Returns -1 on failure. */
238void* VG_(mmap)( void* start, UInt length,
239 UInt prot, UInt flags, UInt fd, UInt offset)
240{
241 Int res;
242 UInt args[6];
243 args[0] = (UInt)start;
244 args[1] = length;
245 args[2] = prot;
246 args[3] = flags;
247 args[4] = fd;
248 args[5] = offset;
249 res = vg_do_syscall1(__NR_mmap, (UInt)(&(args[0])) );
250 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
251}
252
253/* Returns -1 on failure. */
254Int VG_(munmap)( void* start, Int length )
255{
256 Int res = vg_do_syscall2(__NR_munmap, (UInt)start, (UInt)length );
257 return VG_(is_kerror)(res) ? -1 : 0;
258}
259
260void VG_(exit)( Int status )
261{
262 (void)vg_do_syscall1(__NR_exit, (UInt)status );
263 /* Why are we still alive here? */
264 /*NOTREACHED*/
265 vg_assert(2+2 == 5);
266}
267
sewardj2e93c502002-04-12 11:12:52 +0000268/* Returns -1 on error. */
269Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
270{
271 Int res = vg_do_syscall3(__NR_fcntl, fd, cmd, arg);
272 return VG_(is_kerror)(res) ? -1 : res;
273}
274
275/* Returns -1 on error. */
276Int VG_(select)( Int n,
277 vki_fd_set* readfds,
278 vki_fd_set* writefds,
279 vki_fd_set* exceptfds,
280 struct vki_timeval * timeout )
281{
282 Int res;
283 UInt args[5];
284 args[0] = n;
285 args[1] = (UInt)readfds;
286 args[2] = (UInt)writefds;
287 args[3] = (UInt)exceptfds;
288 args[4] = (UInt)timeout;
289 res = vg_do_syscall1(__NR_select, (UInt)(&(args[0])) );
290 return VG_(is_kerror)(res) ? -1 : res;
sewardj2e93c502002-04-12 11:12:52 +0000291}
292
sewardj5f07b662002-04-23 16:52:51 +0000293/* Returns -1 on error, 0 if ok, 1 if interrupted. */
sewardj2e93c502002-04-12 11:12:52 +0000294Int VG_(nanosleep)( const struct vki_timespec *req,
295 struct vki_timespec *rem )
296{
297 Int res;
298 res = vg_do_syscall2(__NR_nanosleep, (UInt)req, (UInt)rem);
299 if (res == -VKI_EINVAL) return -1;
sewardj5f07b662002-04-23 16:52:51 +0000300 if (res == -VKI_EINTR) return 1;
sewardj2e93c502002-04-12 11:12:52 +0000301 return 0;
302}
303
sewardjb3586202002-05-09 17:38:13 +0000304void* VG_(brk) ( void* end_data_segment )
305{
306 Int res;
307 res = vg_do_syscall1(__NR_brk, (UInt)end_data_segment);
308 return (void*)( VG_(is_kerror)(res) ? -1 : res );
309}
310
sewardj2e93c502002-04-12 11:12:52 +0000311
sewardjde4a1d02002-03-22 01:27:54 +0000312/* ---------------------------------------------------------------------
313 printf implementation. The key function, vg_vprintf(), emits chars
314 into a caller-supplied function. Distantly derived from:
315
316 vprintf replacement for Checker.
317 Copyright 1993, 1994, 1995 Tristan Gingold
318 Written September 1993 Tristan Gingold
319 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
320
321 (Checker itself was GPL'd.)
322 ------------------------------------------------------------------ */
323
324
325/* Some flags. */
326#define VG_MSG_SIGNED 1 /* The value is signed. */
327#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
328#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
329
330
331/* Copy a string into the buffer. */
332static void
333myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
334 Bool capitalise )
335{
336# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
337
338 Int i, extra;
339 Int len = VG_(strlen)(str);
340
341 if (width == 0) {
342 for (i = 0; i < len; i++)
343 send(MAYBE_TOUPPER(str[i]));
344 return;
345 }
346
347 if (len > width) {
348 for (i = 0; i < width; i++)
349 send(MAYBE_TOUPPER(str[i]));
350 return;
351 }
352
353 extra = width - len;
354 if (flags & VG_MSG_LJUSTIFY) {
355 for (i = 0; i < extra; i++)
356 send(' ');
357 }
358 for (i = 0; i < len; i++)
359 send(MAYBE_TOUPPER(str[i]));
360 if (!(flags & VG_MSG_LJUSTIFY)) {
361 for (i = 0; i < extra; i++)
362 send(' ');
363 }
364
365# undef MAYBE_TOUPPER
366}
367
368/* Write P into the buffer according to these args:
369 * If SIGN is true, p is a signed.
370 * BASE is the base.
371 * If WITH_ZERO is true, '0' must be added.
372 * WIDTH is the width of the field.
373 */
374static void
375myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
376{
377 Char buf[40];
378 Int ind = 0;
379 Int i;
380 Bool neg = False;
381 Char *digits = "0123456789ABCDEF";
382
383 if (base < 2 || base > 16)
384 return;
385
386 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
387 p = - (Long)p;
388 neg = True;
389 }
390
391 if (p == 0)
392 buf[ind++] = '0';
393 else {
394 while (p > 0) {
395 buf[ind++] = digits[p % base];
396 p /= base;
397 }
398 }
399
400 if (neg)
401 buf[ind++] = '-';
402
403 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
404 for(; ind < width; ind++) {
405 vg_assert(ind < 39);
406 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
407 }
408 }
409
410 /* Reverse copy to buffer. */
411 for (i = ind -1; i >= 0; i--)
412 send(buf[i]);
413
414 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
415 for(; ind < width; ind++)
416 send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
417 }
418}
419
420
421/* A simple vprintf(). */
422void
423VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
424{
425 int i;
426 int flags;
427 int width;
428 Bool is_long;
429
430 /* We assume that vargs has already been initialised by the
431 caller, using va_start, and that the caller will similarly
432 clean up with va_end.
433 */
434
435 for (i = 0; format[i] != 0; i++) {
436 if (format[i] != '%') {
437 send(format[i]);
438 continue;
439 }
440 i++;
441 /* A '%' has been found. Ignore a trailing %. */
442 if (format[i] == 0)
443 break;
444 if (format[i] == '%') {
445 /* `%%' is replaced by `%'. */
446 send('%');
447 continue;
448 }
449 flags = 0;
450 is_long = False;
451 width = 0; /* length of the field. */
452 /* If '-' follows '%', justify on the left. */
453 if (format[i] == '-') {
454 flags |= VG_MSG_LJUSTIFY;
455 i++;
456 }
457 /* If '0' follows '%', pads will be inserted. */
458 if (format[i] == '0') {
459 flags |= VG_MSG_ZJUSTIFY;
460 i++;
461 }
462 /* Compute the field length. */
463 while (format[i] >= '0' && format[i] <= '9') {
464 width *= 10;
465 width += format[i++] - '0';
466 }
467 while (format[i] == 'l') {
468 i++;
469 is_long = True;
470 }
471
472 switch (format[i]) {
473 case 'd': /* %d */
474 flags |= VG_MSG_SIGNED;
475 if (is_long)
476 myvprintf_int64(send, flags, 10, width,
477 (ULong)(va_arg (vargs, Long)));
478 else
479 myvprintf_int64(send, flags, 10, width,
480 (ULong)(va_arg (vargs, Int)));
481 break;
482 case 'u': /* %u */
483 if (is_long)
484 myvprintf_int64(send, flags, 10, width,
485 (ULong)(va_arg (vargs, ULong)));
486 else
487 myvprintf_int64(send, flags, 10, width,
488 (ULong)(va_arg (vargs, UInt)));
489 break;
490 case 'p': /* %p */
491 send('0');
492 send('x');
493 myvprintf_int64(send, flags, 16, width,
494 (ULong)((UInt)va_arg (vargs, void *)));
495 break;
496 case 'x': /* %x */
497 if (is_long)
498 myvprintf_int64(send, flags, 16, width,
499 (ULong)(va_arg (vargs, ULong)));
500 else
501 myvprintf_int64(send, flags, 16, width,
502 (ULong)(va_arg (vargs, UInt)));
503 break;
504 case 'c': /* %c */
505 send(va_arg (vargs, int));
506 break;
507 case 's': case 'S': { /* %s */
508 char *str = va_arg (vargs, char *);
509 if (str == (char*) 0) str = "(null)";
510 myvprintf_str(send, flags, width, str, format[i]=='S');
511 break;
512 }
513 default:
514 break;
515 }
516 }
517}
518
519
520/* A general replacement for printf(). Note that only low-level
521 debugging info should be sent via here. The official route is to
522 to use vg_message(). This interface is deprecated.
523*/
524static char myprintf_buf[100];
525static int n_myprintf_buf;
526
527static void add_to_myprintf_buf ( Char c )
528{
529 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
530 if (VG_(clo_logfile_fd) >= 0)
531 VG_(write)
532 (VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
533 n_myprintf_buf = 0;
534 myprintf_buf[n_myprintf_buf] = 0;
535 }
536 myprintf_buf[n_myprintf_buf++] = c;
537 myprintf_buf[n_myprintf_buf] = 0;
538}
539
540void VG_(printf) ( const char *format, ... )
541{
542 va_list vargs;
543 va_start(vargs,format);
544
545 n_myprintf_buf = 0;
546 myprintf_buf[n_myprintf_buf] = 0;
547 VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
548
549 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0)
550 VG_(write)
551 ( VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
552
553 va_end(vargs);
554}
555
556
557/* A general replacement for sprintf(). */
558static Char* vg_sprintf_ptr;
559
560static void add_to_vg_sprintf_buf ( Char c )
561{
562 *vg_sprintf_ptr++ = c;
563}
564
565void VG_(sprintf) ( Char* buf, Char *format, ... )
566{
567 va_list vargs;
568 va_start(vargs,format);
569
570 vg_sprintf_ptr = buf;
571 VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
572 add_to_vg_sprintf_buf(0);
573
574 va_end(vargs);
575}
576
577
578/* ---------------------------------------------------------------------
579 Misc str* functions.
580 ------------------------------------------------------------------ */
581
582Bool VG_(isspace) ( Char c )
583{
584 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
585}
586
587
588Int VG_(strlen) ( const Char* str )
589{
590 Int i = 0;
591 while (str[i] != 0) i++;
592 return i;
593}
594
595
596Long VG_(atoll) ( Char* str )
597{
598 Bool neg = False;
599 Long n = 0;
600 if (*str == '-') { str++; neg = True; };
601 while (*str >= '0' && *str <= '9') {
602 n = 10*n + (Long)(*str - '0');
603 str++;
604 }
605 if (neg) n = -n;
606 return n;
607}
608
609
610Char* VG_(strcat) ( Char* dest, const Char* src )
611{
612 Char* dest_orig = dest;
613 while (*dest) dest++;
614 while (*src) *dest++ = *src++;
615 *dest = 0;
616 return dest_orig;
617}
618
619
620Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
621{
622 Char* dest_orig = dest;
623 while (*dest) dest++;
624 while (*src && n > 0) { *dest++ = *src++; n--; }
625 *dest = 0;
626 return dest_orig;
627}
628
629
630Char* VG_(strpbrk) ( const Char* s, const Char* accept )
631{
632 const Char* a;
633 while (*s) {
634 a = accept;
635 while (*a)
636 if (*a++ == *s)
637 return (Char *) s;
638 s++;
639 }
640 return NULL;
641}
642
643
644Char* VG_(strcpy) ( Char* dest, const Char* src )
645{
646 Char* dest_orig = dest;
647 while (*src) *dest++ = *src++;
648 *dest = 0;
649 return dest_orig;
650}
651
652
653/* Copy bytes, not overrunning the end of dest and always ensuring
654 zero termination. */
655void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
656{
657 Int i;
658 vg_assert(ndest > 0);
659 i = 0;
660 dest[i] = 0;
661 while (True) {
662 if (src[i] == 0) return;
663 if (i >= ndest-1) return;
664 dest[i] = src[i];
665 i++;
666 dest[i] = 0;
667 }
668}
669
670
671void VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
672{
673 VG_(strncpy_safely)( dest, src, ndest+1 );
674}
675
676
677Int VG_(strcmp) ( const Char* s1, const Char* s2 )
678{
679 while (True) {
680 if (*s1 == 0 && *s2 == 0) return 0;
681 if (*s1 == 0) return -1;
682 if (*s2 == 0) return 1;
683
684 if (*(UChar*)s1 < *(UChar*)s2) return -1;
685 if (*(UChar*)s1 > *(UChar*)s2) return 1;
686
687 s1++; s2++;
688 }
689}
690
691
692Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
693{
694 while (True) {
695 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
696 if (VG_(isspace)(*s1)) return -1;
697 if (VG_(isspace)(*s2)) return 1;
698
699 if (*(UChar*)s1 < *(UChar*)s2) return -1;
700 if (*(UChar*)s1 > *(UChar*)s2) return 1;
701
702 s1++; s2++;
703 }
704}
705
706
707Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
708{
709 Int n = 0;
710 while (True) {
711 if (n >= nmax) return 0;
712 if (*s1 == 0 && *s2 == 0) return 0;
713 if (*s1 == 0) return -1;
714 if (*s2 == 0) return 1;
715
716 if (*(UChar*)s1 < *(UChar*)s2) return -1;
717 if (*(UChar*)s1 > *(UChar*)s2) return 1;
718
719 s1++; s2++; n++;
720 }
721}
722
723
724Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
725{
726 Int n = 0;
727 while (True) {
728 if (n >= nmax) return 0;
729 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
730 if (VG_(isspace)(*s1)) return -1;
731 if (VG_(isspace)(*s2)) return 1;
732
733 if (*(UChar*)s1 < *(UChar*)s2) return -1;
734 if (*(UChar*)s1 > *(UChar*)s2) return 1;
735
736 s1++; s2++; n++;
737 }
738}
739
740
741Char* VG_(strstr) ( const Char* haystack, Char* needle )
742{
743 Int n = VG_(strlen)(needle);
744 while (True) {
745 if (haystack[0] == 0)
746 return NULL;
747 if (VG_(strncmp)(haystack, needle, n) == 0)
748 return (Char*)haystack;
749 haystack++;
750 }
751}
752
753
754Char* VG_(strchr) ( const Char* s, Char c )
755{
756 while (True) {
757 if (*s == c) return (Char*)s;
758 if (*s == 0) return NULL;
759 s++;
760 }
761}
762
763
764Char VG_(toupper) ( Char c )
765{
766 if (c >= 'a' && c <= 'z')
767 return c + ('A' - 'a');
768 else
769 return c;
770}
771
772
773Char* VG_(strdup) ( ArenaId aid, const Char* s )
774{
775 Int i;
776 Int len = VG_(strlen)(s) + 1;
777 Char* res = VG_(malloc) (aid, len);
778 for (i = 0; i < len; i++)
779 res[i] = s[i];
780 return res;
781}
782
783
784/* ---------------------------------------------------------------------
785 A simple string matching routine, purloined from Hugs98.
786 `*' matches any sequence of zero or more characters
787 `?' matches any single character exactly
788 `\c' matches the character c only (ignoring special chars)
789 c matches the character c only
790 ------------------------------------------------------------------ */
791
792/* Keep track of recursion depth. */
793static Int recDepth;
794
795static Bool stringMatch_wrk ( Char* pat, Char* str )
796{
797 vg_assert(recDepth >= 0 && recDepth < 500);
798 recDepth++;
799 for (;;) {
800 switch (*pat) {
801 case '\0' : return (*str=='\0');
802 case '*' : do {
803 if (stringMatch_wrk(pat+1,str)) {
804 recDepth--;
805 return True;
806 }
807 } while (*str++);
808 recDepth--;
809 return False;
810 case '?' : if (*str++=='\0') {
811 recDepth--;
812 return False;
813 }
814 pat++;
815 break;
816 case '\\' : if (*++pat == '\0') {
817 recDepth--;
818 return False; /* spurious trailing \ in pattern */
819 }
820 /* falls through to ... */
821 default : if (*pat++ != *str++) {
822 recDepth--;
823 return False;
824 }
825 break;
826 }
827 }
828}
829
830Bool VG_(stringMatch) ( Char* pat, Char* str )
831{
832 Bool b;
833 recDepth = 0;
834 b = stringMatch_wrk ( pat, str );
835 /*
836 VG_(printf)("%s %s %s\n",
837 b?"TRUE ":"FALSE", pat, str);
838 */
839 return b;
840}
841
842
843/* ---------------------------------------------------------------------
844 Assertery.
845 ------------------------------------------------------------------ */
846
847#define EMAIL_ADDR "jseward@acm.org"
848
849void VG_(assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
850{
851 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
852 "valgrind", file, line, fn, expr );
sewardj15a43e12002-04-17 19:35:12 +0000853 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +0000854 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
855 VG_(shutdown_logging)();
sewardjde4a1d02002-03-22 01:27:54 +0000856 VG_(exit)(1);
857}
858
859void VG_(panic) ( Char* str )
860{
861 VG_(printf)("\nvalgrind: the `impossible' happened:\n %s\n", str);
862 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
sewardj15a43e12002-04-17 19:35:12 +0000863 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +0000864 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
865 VG_(shutdown_logging)();
sewardjde4a1d02002-03-22 01:27:54 +0000866 VG_(exit)(1);
867}
868
869#undef EMAIL_ADDR
870
871
872/* ---------------------------------------------------------------------
873 Primitive support for reading files.
874 ------------------------------------------------------------------ */
875
876/* Returns -1 on failure. */
877Int VG_(open_read) ( Char* pathname )
878{
879 Int fd;
880 /* VG_(printf)("vg_open_read %s\n", pathname ); */
881
882 /* This gets a segmentation fault if pathname isn't a valid file.
883 I don't know why. It seems like the call to open is getting
884 intercepted and messed with by glibc ... */
885 /* fd = open( pathname, O_RDONLY ); */
886 /* ... so we go direct to the horse's mouth, which seems to work
887 ok: */
888 const int O_RDONLY = 0; /* See /usr/include/bits/fcntl.h */
889 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_RDONLY, 0);
890 /* VG_(printf)("result = %d\n", fd); */
891 if (VG_(is_kerror)(fd)) fd = -1;
892 return fd;
893}
njn4f9c9342002-04-29 16:03:24 +0000894
895/* Returns -1 on failure. */
896static Int VG_(chmod_u_rw) ( Int fd )
897{
898 Int res;
899 const int O_IRUSR_IWUSR = 000600; /* See /usr/include/cpio.h */
900 res = vg_do_syscall2(__NR_fchmod, fd, O_IRUSR_IWUSR);
901 if (VG_(is_kerror)(res)) res = -1;
902 return res;
903}
sewardjde4a1d02002-03-22 01:27:54 +0000904
njn4f9c9342002-04-29 16:03:24 +0000905/* Returns -1 on failure. */
906Int VG_(create_and_write) ( Char* pathname )
907{
908 Int fd;
909
910 const int O_CR_AND_WR_ONLY = 0101; /* See /usr/include/bits/fcntl.h */
911 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_CR_AND_WR_ONLY, 0);
912 /* VG_(printf)("result = %d\n", fd); */
913 if (VG_(is_kerror)(fd)) {
914 fd = -1;
915 } else {
916 VG_(chmod_u_rw)(fd);
917 if (VG_(is_kerror)(fd)) {
918 fd = -1;
919 }
920 }
921 return fd;
922}
923
924/* Returns -1 on failure. */
925Int VG_(open_write) ( Char* pathname )
926{
927 Int fd;
928
929 const int O_WRONLY_AND_TRUNC = 01001; /* See /usr/include/bits/fcntl.h */
930 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_WRONLY_AND_TRUNC, 0);
931 /* VG_(printf)("result = %d\n", fd); */
932 if (VG_(is_kerror)(fd)) {
933 fd = -1;
934 }
935 return fd;
936}
sewardjde4a1d02002-03-22 01:27:54 +0000937
938void VG_(close) ( Int fd )
939{
940 vg_do_syscall1(__NR_close, fd);
941}
942
943
944Int VG_(read) ( Int fd, void* buf, Int count)
945{
946 Int res;
947 /* res = read( fd, buf, count ); */
948 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
949 if (VG_(is_kerror)(res)) res = -1;
950 return res;
951}
952
953Int VG_(write) ( Int fd, void* buf, Int count)
954{
955 Int res;
956 /* res = write( fd, buf, count ); */
957 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
958 if (VG_(is_kerror)(res)) res = -1;
959 return res;
960}
961
sewardjb3586202002-05-09 17:38:13 +0000962Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
963{
964 Int res;
965 res = vg_do_syscall2(__NR_stat, (UInt)file_name, (UInt)buf);
966 return
967 VG_(is_kerror)(res) ? (-1) : 0;
968}
969
sewardjde4a1d02002-03-22 01:27:54 +0000970/* Misc functions looking for a proper home. */
971
972/* We do getenv without libc's help by snooping around in
973 VG_(client_env) as determined at startup time. */
974Char* VG_(getenv) ( Char* varname )
975{
976 Int i, n;
977 n = VG_(strlen)(varname);
978 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
979 Char* s = VG_(client_envp)[i];
980 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
981 return & s[n+1];
982 }
983 }
984 return NULL;
985}
986
987/* You'd be amazed how many places need to know the current pid. */
988Int VG_(getpid) ( void )
989{
990 Int res;
991 /* res = getpid(); */
992 res = vg_do_syscall0(__NR_getpid);
993 return res;
994}
995
sewardje6a25242002-04-21 22:03:07 +0000996/* Return -1 if error, else 0. NOTE does not indicate return code of
997 child! */
998Int VG_(system) ( Char* cmd )
999{
1000 Int pid, res;
1001 void* environ[1] = { NULL };
1002 if (cmd == NULL)
1003 return 1;
1004 pid = vg_do_syscall0(__NR_fork);
1005 if (VG_(is_kerror)(pid))
1006 return -1;
1007 if (pid == 0) {
1008 /* child */
1009 Char* argv[4];
1010 argv[0] = "/bin/sh";
1011 argv[1] = "-c";
1012 argv[2] = cmd;
1013 argv[3] = 0;
1014 (void)vg_do_syscall3(__NR_execve,
1015 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
1016 /* If we're still alive here, execve failed. */
1017 return -1;
1018 } else {
1019 /* parent */
1020 res = vg_do_syscall3(__NR_waitpid, pid, (UInt)NULL, 0);
1021 if (VG_(is_kerror)(res)) {
1022 return -1;
1023 } else {
1024 return 0;
1025 }
1026 }
1027}
1028
1029
sewardjde4a1d02002-03-22 01:27:54 +00001030/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001031 Support for a millisecond-granularity counter using RDTSC.
1032 ------------------------------------------------------------------ */
1033
1034static __inline__ ULong do_rdtsc_insn ( void )
1035{
1036 ULong x;
1037 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1038 return x;
1039}
1040
1041/* 0 = pre-calibration, 1 = calibration, 2 = running */
1042static Int rdtsc_calibration_state = 0;
1043static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1044
1045static struct vki_timeval rdtsc_cal_start_timeval;
1046static struct vki_timeval rdtsc_cal_end_timeval;
1047
1048static ULong rdtsc_cal_start_raw;
1049static ULong rdtsc_cal_end_raw;
1050
1051UInt VG_(read_millisecond_timer) ( void )
1052{
1053 ULong rdtsc_now;
1054 vg_assert(rdtsc_calibration_state == 2);
1055 rdtsc_now = do_rdtsc_insn();
1056 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1057 rdtsc_now -= rdtsc_cal_end_raw;
1058 rdtsc_now /= rdtsc_ticks_per_millisecond;
1059 return (UInt)rdtsc_now;
1060}
1061
1062
1063void VG_(start_rdtsc_calibration) ( void )
1064{
1065 Int res;
1066 vg_assert(rdtsc_calibration_state == 0);
1067 rdtsc_calibration_state = 1;
1068 rdtsc_cal_start_raw = do_rdtsc_insn();
1069 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1070 (UInt)NULL);
1071 vg_assert(!VG_(is_kerror)(res));
1072}
1073
1074void VG_(end_rdtsc_calibration) ( void )
1075{
1076 Int res, loops;
1077 ULong cpu_clock_MHZ;
1078 ULong cal_clock_ticks;
1079 ULong cal_wallclock_microseconds;
1080 ULong wallclock_start_microseconds;
1081 ULong wallclock_end_microseconds;
1082 struct vki_timespec req;
1083 struct vki_timespec rem;
1084
1085 vg_assert(rdtsc_calibration_state == 1);
1086 rdtsc_calibration_state = 2;
1087
1088 /* Try and delay for 20 milliseconds, so that we can at least have
1089 some minimum level of accuracy. */
1090 req.tv_sec = 0;
1091 req.tv_nsec = 20 * 1000 * 1000;
1092 loops = 0;
1093 while (True) {
1094 res = VG_(nanosleep)(&req, &rem);
1095 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1096 if (res == 0)
1097 break;
1098 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1099 break;
1100 req = rem;
1101 loops++;
1102 if (loops > 100)
1103 VG_(panic)("calibration nanosleep loop failed?!");
1104 }
1105
1106 /* Now read both timers, and do the Math. */
1107 rdtsc_cal_end_raw = do_rdtsc_insn();
1108 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1109 (UInt)NULL);
1110
1111 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1112 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1113
1114 wallclock_start_microseconds
1115 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1116 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1117 wallclock_end_microseconds
1118 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1119 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1120 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1121 cal_wallclock_microseconds
1122 = wallclock_end_microseconds - wallclock_start_microseconds;
1123
1124 /* Since we just nanoslept for 20 ms ... */
1125 vg_assert(cal_wallclock_microseconds >= 20000);
1126
1127 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1128 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1129 ticks-per-millisecond value. */
1130 if (0)
1131 VG_(printf)("%lld ticks in %lld microseconds\n",
1132 cal_clock_ticks, cal_wallclock_microseconds );
1133
1134 rdtsc_ticks_per_millisecond
1135 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1136 cpu_clock_MHZ
1137 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1138 if (VG_(clo_verbosity) >= 1)
1139 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1140 (UInt)cpu_clock_MHZ);
1141 if (cpu_clock_MHZ < 100 || cpu_clock_MHZ > 10000)
1142 VG_(panic)("end_rdtsc_calibration: "
1143 "estimated CPU MHz outside range 100 .. 10000");
1144 /* Paranoia about division by zero later. */
1145 vg_assert(rdtsc_ticks_per_millisecond != 0);
1146 if (0)
1147 VG_(printf)("ticks per millisecond %llu\n",
1148 rdtsc_ticks_per_millisecond);
1149}
1150
1151
1152
1153/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001154 Primitive support for bagging memory via mmap.
1155 ------------------------------------------------------------------ */
1156
1157void* VG_(get_memory_from_mmap) ( Int nBytes )
1158{
1159 static UInt tot_alloc = 0;
1160 void* p = VG_(mmap)( 0, nBytes,
1161 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1162 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
1163 if (p != ((void*)(-1))) {
1164 tot_alloc += (UInt)nBytes;
1165 if (0)
1166 VG_(printf)("get_memory_from_mmap: %d tot, %d req\n",
1167 tot_alloc, nBytes);
1168 return p;
1169 }
1170 VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n",
1171 nBytes);
1172 VG_(panic)("vg_get_memory_from_mmap: out of memory! Fatal! Bye!\n");
1173}
1174
1175
1176/*--------------------------------------------------------------------*/
1177/*--- end vg_mylibc.c ---*/
1178/*--------------------------------------------------------------------*/