blob: 77dd153a2e1331b7907a93ac6efd167d34a66914 [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;
291 return res;
292}
293
sewardj5f07b662002-04-23 16:52:51 +0000294/* Returns -1 on error, 0 if ok, 1 if interrupted. */
sewardj2e93c502002-04-12 11:12:52 +0000295Int VG_(nanosleep)( const struct vki_timespec *req,
296 struct vki_timespec *rem )
297{
298 Int res;
299 res = vg_do_syscall2(__NR_nanosleep, (UInt)req, (UInt)rem);
300 if (res == -VKI_EINVAL) return -1;
sewardj5f07b662002-04-23 16:52:51 +0000301 if (res == -VKI_EINTR) return 1;
sewardj2e93c502002-04-12 11:12:52 +0000302 return 0;
303}
304
305
sewardjde4a1d02002-03-22 01:27:54 +0000306/* ---------------------------------------------------------------------
307 printf implementation. The key function, vg_vprintf(), emits chars
308 into a caller-supplied function. Distantly derived from:
309
310 vprintf replacement for Checker.
311 Copyright 1993, 1994, 1995 Tristan Gingold
312 Written September 1993 Tristan Gingold
313 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
314
315 (Checker itself was GPL'd.)
316 ------------------------------------------------------------------ */
317
318
319/* Some flags. */
320#define VG_MSG_SIGNED 1 /* The value is signed. */
321#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
322#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
323
324
325/* Copy a string into the buffer. */
326static void
327myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
328 Bool capitalise )
329{
330# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
331
332 Int i, extra;
333 Int len = VG_(strlen)(str);
334
335 if (width == 0) {
336 for (i = 0; i < len; i++)
337 send(MAYBE_TOUPPER(str[i]));
338 return;
339 }
340
341 if (len > width) {
342 for (i = 0; i < width; i++)
343 send(MAYBE_TOUPPER(str[i]));
344 return;
345 }
346
347 extra = width - len;
348 if (flags & VG_MSG_LJUSTIFY) {
349 for (i = 0; i < extra; i++)
350 send(' ');
351 }
352 for (i = 0; i < len; i++)
353 send(MAYBE_TOUPPER(str[i]));
354 if (!(flags & VG_MSG_LJUSTIFY)) {
355 for (i = 0; i < extra; i++)
356 send(' ');
357 }
358
359# undef MAYBE_TOUPPER
360}
361
362/* Write P into the buffer according to these args:
363 * If SIGN is true, p is a signed.
364 * BASE is the base.
365 * If WITH_ZERO is true, '0' must be added.
366 * WIDTH is the width of the field.
367 */
368static void
369myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
370{
371 Char buf[40];
372 Int ind = 0;
373 Int i;
374 Bool neg = False;
375 Char *digits = "0123456789ABCDEF";
376
377 if (base < 2 || base > 16)
378 return;
379
380 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
381 p = - (Long)p;
382 neg = True;
383 }
384
385 if (p == 0)
386 buf[ind++] = '0';
387 else {
388 while (p > 0) {
389 buf[ind++] = digits[p % base];
390 p /= base;
391 }
392 }
393
394 if (neg)
395 buf[ind++] = '-';
396
397 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
398 for(; ind < width; ind++) {
399 vg_assert(ind < 39);
400 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
401 }
402 }
403
404 /* Reverse copy to buffer. */
405 for (i = ind -1; i >= 0; i--)
406 send(buf[i]);
407
408 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
409 for(; ind < width; ind++)
410 send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
411 }
412}
413
414
415/* A simple vprintf(). */
416void
417VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
418{
419 int i;
420 int flags;
421 int width;
422 Bool is_long;
423
424 /* We assume that vargs has already been initialised by the
425 caller, using va_start, and that the caller will similarly
426 clean up with va_end.
427 */
428
429 for (i = 0; format[i] != 0; i++) {
430 if (format[i] != '%') {
431 send(format[i]);
432 continue;
433 }
434 i++;
435 /* A '%' has been found. Ignore a trailing %. */
436 if (format[i] == 0)
437 break;
438 if (format[i] == '%') {
439 /* `%%' is replaced by `%'. */
440 send('%');
441 continue;
442 }
443 flags = 0;
444 is_long = False;
445 width = 0; /* length of the field. */
446 /* If '-' follows '%', justify on the left. */
447 if (format[i] == '-') {
448 flags |= VG_MSG_LJUSTIFY;
449 i++;
450 }
451 /* If '0' follows '%', pads will be inserted. */
452 if (format[i] == '0') {
453 flags |= VG_MSG_ZJUSTIFY;
454 i++;
455 }
456 /* Compute the field length. */
457 while (format[i] >= '0' && format[i] <= '9') {
458 width *= 10;
459 width += format[i++] - '0';
460 }
461 while (format[i] == 'l') {
462 i++;
463 is_long = True;
464 }
465
466 switch (format[i]) {
467 case 'd': /* %d */
468 flags |= VG_MSG_SIGNED;
469 if (is_long)
470 myvprintf_int64(send, flags, 10, width,
471 (ULong)(va_arg (vargs, Long)));
472 else
473 myvprintf_int64(send, flags, 10, width,
474 (ULong)(va_arg (vargs, Int)));
475 break;
476 case 'u': /* %u */
477 if (is_long)
478 myvprintf_int64(send, flags, 10, width,
479 (ULong)(va_arg (vargs, ULong)));
480 else
481 myvprintf_int64(send, flags, 10, width,
482 (ULong)(va_arg (vargs, UInt)));
483 break;
484 case 'p': /* %p */
485 send('0');
486 send('x');
487 myvprintf_int64(send, flags, 16, width,
488 (ULong)((UInt)va_arg (vargs, void *)));
489 break;
490 case 'x': /* %x */
491 if (is_long)
492 myvprintf_int64(send, flags, 16, width,
493 (ULong)(va_arg (vargs, ULong)));
494 else
495 myvprintf_int64(send, flags, 16, width,
496 (ULong)(va_arg (vargs, UInt)));
497 break;
498 case 'c': /* %c */
499 send(va_arg (vargs, int));
500 break;
501 case 's': case 'S': { /* %s */
502 char *str = va_arg (vargs, char *);
503 if (str == (char*) 0) str = "(null)";
504 myvprintf_str(send, flags, width, str, format[i]=='S');
505 break;
506 }
507 default:
508 break;
509 }
510 }
511}
512
513
514/* A general replacement for printf(). Note that only low-level
515 debugging info should be sent via here. The official route is to
516 to use vg_message(). This interface is deprecated.
517*/
518static char myprintf_buf[100];
519static int n_myprintf_buf;
520
521static void add_to_myprintf_buf ( Char c )
522{
523 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
524 if (VG_(clo_logfile_fd) >= 0)
525 VG_(write)
526 (VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
527 n_myprintf_buf = 0;
528 myprintf_buf[n_myprintf_buf] = 0;
529 }
530 myprintf_buf[n_myprintf_buf++] = c;
531 myprintf_buf[n_myprintf_buf] = 0;
532}
533
534void VG_(printf) ( const char *format, ... )
535{
536 va_list vargs;
537 va_start(vargs,format);
538
539 n_myprintf_buf = 0;
540 myprintf_buf[n_myprintf_buf] = 0;
541 VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
542
543 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0)
544 VG_(write)
545 ( VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
546
547 va_end(vargs);
548}
549
550
551/* A general replacement for sprintf(). */
552static Char* vg_sprintf_ptr;
553
554static void add_to_vg_sprintf_buf ( Char c )
555{
556 *vg_sprintf_ptr++ = c;
557}
558
559void VG_(sprintf) ( Char* buf, Char *format, ... )
560{
561 va_list vargs;
562 va_start(vargs,format);
563
564 vg_sprintf_ptr = buf;
565 VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
566 add_to_vg_sprintf_buf(0);
567
568 va_end(vargs);
569}
570
571
572/* ---------------------------------------------------------------------
573 Misc str* functions.
574 ------------------------------------------------------------------ */
575
576Bool VG_(isspace) ( Char c )
577{
578 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
579}
580
581
582Int VG_(strlen) ( const Char* str )
583{
584 Int i = 0;
585 while (str[i] != 0) i++;
586 return i;
587}
588
589
590Long VG_(atoll) ( Char* str )
591{
592 Bool neg = False;
593 Long n = 0;
594 if (*str == '-') { str++; neg = True; };
595 while (*str >= '0' && *str <= '9') {
596 n = 10*n + (Long)(*str - '0');
597 str++;
598 }
599 if (neg) n = -n;
600 return n;
601}
602
603
604Char* VG_(strcat) ( Char* dest, const Char* src )
605{
606 Char* dest_orig = dest;
607 while (*dest) dest++;
608 while (*src) *dest++ = *src++;
609 *dest = 0;
610 return dest_orig;
611}
612
613
614Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
615{
616 Char* dest_orig = dest;
617 while (*dest) dest++;
618 while (*src && n > 0) { *dest++ = *src++; n--; }
619 *dest = 0;
620 return dest_orig;
621}
622
623
624Char* VG_(strpbrk) ( const Char* s, const Char* accept )
625{
626 const Char* a;
627 while (*s) {
628 a = accept;
629 while (*a)
630 if (*a++ == *s)
631 return (Char *) s;
632 s++;
633 }
634 return NULL;
635}
636
637
638Char* VG_(strcpy) ( Char* dest, const Char* src )
639{
640 Char* dest_orig = dest;
641 while (*src) *dest++ = *src++;
642 *dest = 0;
643 return dest_orig;
644}
645
646
647/* Copy bytes, not overrunning the end of dest and always ensuring
648 zero termination. */
649void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
650{
651 Int i;
652 vg_assert(ndest > 0);
653 i = 0;
654 dest[i] = 0;
655 while (True) {
656 if (src[i] == 0) return;
657 if (i >= ndest-1) return;
658 dest[i] = src[i];
659 i++;
660 dest[i] = 0;
661 }
662}
663
664
665void VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
666{
667 VG_(strncpy_safely)( dest, src, ndest+1 );
668}
669
670
671Int VG_(strcmp) ( const Char* s1, const Char* s2 )
672{
673 while (True) {
674 if (*s1 == 0 && *s2 == 0) return 0;
675 if (*s1 == 0) return -1;
676 if (*s2 == 0) return 1;
677
678 if (*(UChar*)s1 < *(UChar*)s2) return -1;
679 if (*(UChar*)s1 > *(UChar*)s2) return 1;
680
681 s1++; s2++;
682 }
683}
684
685
686Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
687{
688 while (True) {
689 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
690 if (VG_(isspace)(*s1)) return -1;
691 if (VG_(isspace)(*s2)) return 1;
692
693 if (*(UChar*)s1 < *(UChar*)s2) return -1;
694 if (*(UChar*)s1 > *(UChar*)s2) return 1;
695
696 s1++; s2++;
697 }
698}
699
700
701Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
702{
703 Int n = 0;
704 while (True) {
705 if (n >= nmax) return 0;
706 if (*s1 == 0 && *s2 == 0) return 0;
707 if (*s1 == 0) return -1;
708 if (*s2 == 0) return 1;
709
710 if (*(UChar*)s1 < *(UChar*)s2) return -1;
711 if (*(UChar*)s1 > *(UChar*)s2) return 1;
712
713 s1++; s2++; n++;
714 }
715}
716
717
718Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
719{
720 Int n = 0;
721 while (True) {
722 if (n >= nmax) return 0;
723 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
724 if (VG_(isspace)(*s1)) return -1;
725 if (VG_(isspace)(*s2)) return 1;
726
727 if (*(UChar*)s1 < *(UChar*)s2) return -1;
728 if (*(UChar*)s1 > *(UChar*)s2) return 1;
729
730 s1++; s2++; n++;
731 }
732}
733
734
735Char* VG_(strstr) ( const Char* haystack, Char* needle )
736{
737 Int n = VG_(strlen)(needle);
738 while (True) {
739 if (haystack[0] == 0)
740 return NULL;
741 if (VG_(strncmp)(haystack, needle, n) == 0)
742 return (Char*)haystack;
743 haystack++;
744 }
745}
746
747
748Char* VG_(strchr) ( const Char* s, Char c )
749{
750 while (True) {
751 if (*s == c) return (Char*)s;
752 if (*s == 0) return NULL;
753 s++;
754 }
755}
756
757
758Char VG_(toupper) ( Char c )
759{
760 if (c >= 'a' && c <= 'z')
761 return c + ('A' - 'a');
762 else
763 return c;
764}
765
766
767Char* VG_(strdup) ( ArenaId aid, const Char* s )
768{
769 Int i;
770 Int len = VG_(strlen)(s) + 1;
771 Char* res = VG_(malloc) (aid, len);
772 for (i = 0; i < len; i++)
773 res[i] = s[i];
774 return res;
775}
776
777
778/* ---------------------------------------------------------------------
779 A simple string matching routine, purloined from Hugs98.
780 `*' matches any sequence of zero or more characters
781 `?' matches any single character exactly
782 `\c' matches the character c only (ignoring special chars)
783 c matches the character c only
784 ------------------------------------------------------------------ */
785
786/* Keep track of recursion depth. */
787static Int recDepth;
788
789static Bool stringMatch_wrk ( Char* pat, Char* str )
790{
791 vg_assert(recDepth >= 0 && recDepth < 500);
792 recDepth++;
793 for (;;) {
794 switch (*pat) {
795 case '\0' : return (*str=='\0');
796 case '*' : do {
797 if (stringMatch_wrk(pat+1,str)) {
798 recDepth--;
799 return True;
800 }
801 } while (*str++);
802 recDepth--;
803 return False;
804 case '?' : if (*str++=='\0') {
805 recDepth--;
806 return False;
807 }
808 pat++;
809 break;
810 case '\\' : if (*++pat == '\0') {
811 recDepth--;
812 return False; /* spurious trailing \ in pattern */
813 }
814 /* falls through to ... */
815 default : if (*pat++ != *str++) {
816 recDepth--;
817 return False;
818 }
819 break;
820 }
821 }
822}
823
824Bool VG_(stringMatch) ( Char* pat, Char* str )
825{
826 Bool b;
827 recDepth = 0;
828 b = stringMatch_wrk ( pat, str );
829 /*
830 VG_(printf)("%s %s %s\n",
831 b?"TRUE ":"FALSE", pat, str);
832 */
833 return b;
834}
835
836
837/* ---------------------------------------------------------------------
838 Assertery.
839 ------------------------------------------------------------------ */
840
841#define EMAIL_ADDR "jseward@acm.org"
842
843void VG_(assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
844{
845 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
846 "valgrind", file, line, fn, expr );
sewardj15a43e12002-04-17 19:35:12 +0000847 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +0000848 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
849 VG_(shutdown_logging)();
sewardjde4a1d02002-03-22 01:27:54 +0000850 VG_(exit)(1);
851}
852
853void VG_(panic) ( Char* str )
854{
855 VG_(printf)("\nvalgrind: the `impossible' happened:\n %s\n", str);
856 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
sewardj15a43e12002-04-17 19:35:12 +0000857 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +0000858 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
859 VG_(shutdown_logging)();
sewardjde4a1d02002-03-22 01:27:54 +0000860 VG_(exit)(1);
861}
862
863#undef EMAIL_ADDR
864
865
866/* ---------------------------------------------------------------------
867 Primitive support for reading files.
868 ------------------------------------------------------------------ */
869
870/* Returns -1 on failure. */
871Int VG_(open_read) ( Char* pathname )
872{
873 Int fd;
874 /* VG_(printf)("vg_open_read %s\n", pathname ); */
875
876 /* This gets a segmentation fault if pathname isn't a valid file.
877 I don't know why. It seems like the call to open is getting
878 intercepted and messed with by glibc ... */
879 /* fd = open( pathname, O_RDONLY ); */
880 /* ... so we go direct to the horse's mouth, which seems to work
881 ok: */
882 const int O_RDONLY = 0; /* See /usr/include/bits/fcntl.h */
883 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_RDONLY, 0);
884 /* VG_(printf)("result = %d\n", fd); */
885 if (VG_(is_kerror)(fd)) fd = -1;
886 return fd;
887}
njn4f9c9342002-04-29 16:03:24 +0000888
889/* Returns -1 on failure. */
890static Int VG_(chmod_u_rw) ( Int fd )
891{
892 Int res;
893 const int O_IRUSR_IWUSR = 000600; /* See /usr/include/cpio.h */
894 res = vg_do_syscall2(__NR_fchmod, fd, O_IRUSR_IWUSR);
895 if (VG_(is_kerror)(res)) res = -1;
896 return res;
897}
sewardjde4a1d02002-03-22 01:27:54 +0000898
njn4f9c9342002-04-29 16:03:24 +0000899/* Returns -1 on failure. */
900Int VG_(create_and_write) ( Char* pathname )
901{
902 Int fd;
903
904 const int O_CR_AND_WR_ONLY = 0101; /* See /usr/include/bits/fcntl.h */
905 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_CR_AND_WR_ONLY, 0);
906 /* VG_(printf)("result = %d\n", fd); */
907 if (VG_(is_kerror)(fd)) {
908 fd = -1;
909 } else {
910 VG_(chmod_u_rw)(fd);
911 if (VG_(is_kerror)(fd)) {
912 fd = -1;
913 }
914 }
915 return fd;
916}
917
918/* Returns -1 on failure. */
919Int VG_(open_write) ( Char* pathname )
920{
921 Int fd;
922
923 const int O_WRONLY_AND_TRUNC = 01001; /* See /usr/include/bits/fcntl.h */
924 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_WRONLY_AND_TRUNC, 0);
925 /* VG_(printf)("result = %d\n", fd); */
926 if (VG_(is_kerror)(fd)) {
927 fd = -1;
928 }
929 return fd;
930}
sewardjde4a1d02002-03-22 01:27:54 +0000931
932void VG_(close) ( Int fd )
933{
934 vg_do_syscall1(__NR_close, fd);
935}
936
937
938Int VG_(read) ( Int fd, void* buf, Int count)
939{
940 Int res;
941 /* res = read( fd, buf, count ); */
942 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
943 if (VG_(is_kerror)(res)) res = -1;
944 return res;
945}
946
947Int VG_(write) ( Int fd, void* buf, Int count)
948{
949 Int res;
950 /* res = write( fd, buf, count ); */
951 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
952 if (VG_(is_kerror)(res)) res = -1;
953 return res;
954}
955
956/* Misc functions looking for a proper home. */
957
958/* We do getenv without libc's help by snooping around in
959 VG_(client_env) as determined at startup time. */
960Char* VG_(getenv) ( Char* varname )
961{
962 Int i, n;
963 n = VG_(strlen)(varname);
964 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
965 Char* s = VG_(client_envp)[i];
966 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
967 return & s[n+1];
968 }
969 }
970 return NULL;
971}
972
973/* You'd be amazed how many places need to know the current pid. */
974Int VG_(getpid) ( void )
975{
976 Int res;
977 /* res = getpid(); */
978 res = vg_do_syscall0(__NR_getpid);
979 return res;
980}
981
sewardje6a25242002-04-21 22:03:07 +0000982/* Return -1 if error, else 0. NOTE does not indicate return code of
983 child! */
984Int VG_(system) ( Char* cmd )
985{
986 Int pid, res;
987 void* environ[1] = { NULL };
988 if (cmd == NULL)
989 return 1;
990 pid = vg_do_syscall0(__NR_fork);
991 if (VG_(is_kerror)(pid))
992 return -1;
993 if (pid == 0) {
994 /* child */
995 Char* argv[4];
996 argv[0] = "/bin/sh";
997 argv[1] = "-c";
998 argv[2] = cmd;
999 argv[3] = 0;
1000 (void)vg_do_syscall3(__NR_execve,
1001 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
1002 /* If we're still alive here, execve failed. */
1003 return -1;
1004 } else {
1005 /* parent */
1006 res = vg_do_syscall3(__NR_waitpid, pid, (UInt)NULL, 0);
1007 if (VG_(is_kerror)(res)) {
1008 return -1;
1009 } else {
1010 return 0;
1011 }
1012 }
1013}
1014
1015
sewardjde4a1d02002-03-22 01:27:54 +00001016/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001017 Support for a millisecond-granularity counter using RDTSC.
1018 ------------------------------------------------------------------ */
1019
1020static __inline__ ULong do_rdtsc_insn ( void )
1021{
1022 ULong x;
1023 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1024 return x;
1025}
1026
1027/* 0 = pre-calibration, 1 = calibration, 2 = running */
1028static Int rdtsc_calibration_state = 0;
1029static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1030
1031static struct vki_timeval rdtsc_cal_start_timeval;
1032static struct vki_timeval rdtsc_cal_end_timeval;
1033
1034static ULong rdtsc_cal_start_raw;
1035static ULong rdtsc_cal_end_raw;
1036
1037UInt VG_(read_millisecond_timer) ( void )
1038{
1039 ULong rdtsc_now;
1040 vg_assert(rdtsc_calibration_state == 2);
1041 rdtsc_now = do_rdtsc_insn();
1042 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1043 rdtsc_now -= rdtsc_cal_end_raw;
1044 rdtsc_now /= rdtsc_ticks_per_millisecond;
1045 return (UInt)rdtsc_now;
1046}
1047
1048
1049void VG_(start_rdtsc_calibration) ( void )
1050{
1051 Int res;
1052 vg_assert(rdtsc_calibration_state == 0);
1053 rdtsc_calibration_state = 1;
1054 rdtsc_cal_start_raw = do_rdtsc_insn();
1055 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1056 (UInt)NULL);
1057 vg_assert(!VG_(is_kerror)(res));
1058}
1059
1060void VG_(end_rdtsc_calibration) ( void )
1061{
1062 Int res, loops;
1063 ULong cpu_clock_MHZ;
1064 ULong cal_clock_ticks;
1065 ULong cal_wallclock_microseconds;
1066 ULong wallclock_start_microseconds;
1067 ULong wallclock_end_microseconds;
1068 struct vki_timespec req;
1069 struct vki_timespec rem;
1070
1071 vg_assert(rdtsc_calibration_state == 1);
1072 rdtsc_calibration_state = 2;
1073
1074 /* Try and delay for 20 milliseconds, so that we can at least have
1075 some minimum level of accuracy. */
1076 req.tv_sec = 0;
1077 req.tv_nsec = 20 * 1000 * 1000;
1078 loops = 0;
1079 while (True) {
1080 res = VG_(nanosleep)(&req, &rem);
1081 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1082 if (res == 0)
1083 break;
1084 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1085 break;
1086 req = rem;
1087 loops++;
1088 if (loops > 100)
1089 VG_(panic)("calibration nanosleep loop failed?!");
1090 }
1091
1092 /* Now read both timers, and do the Math. */
1093 rdtsc_cal_end_raw = do_rdtsc_insn();
1094 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1095 (UInt)NULL);
1096
1097 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1098 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1099
1100 wallclock_start_microseconds
1101 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1102 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1103 wallclock_end_microseconds
1104 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1105 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1106 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1107 cal_wallclock_microseconds
1108 = wallclock_end_microseconds - wallclock_start_microseconds;
1109
1110 /* Since we just nanoslept for 20 ms ... */
1111 vg_assert(cal_wallclock_microseconds >= 20000);
1112
1113 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1114 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1115 ticks-per-millisecond value. */
1116 if (0)
1117 VG_(printf)("%lld ticks in %lld microseconds\n",
1118 cal_clock_ticks, cal_wallclock_microseconds );
1119
1120 rdtsc_ticks_per_millisecond
1121 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1122 cpu_clock_MHZ
1123 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1124 if (VG_(clo_verbosity) >= 1)
1125 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1126 (UInt)cpu_clock_MHZ);
1127 if (cpu_clock_MHZ < 100 || cpu_clock_MHZ > 10000)
1128 VG_(panic)("end_rdtsc_calibration: "
1129 "estimated CPU MHz outside range 100 .. 10000");
1130 /* Paranoia about division by zero later. */
1131 vg_assert(rdtsc_ticks_per_millisecond != 0);
1132 if (0)
1133 VG_(printf)("ticks per millisecond %llu\n",
1134 rdtsc_ticks_per_millisecond);
1135}
1136
1137
1138
1139/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001140 Primitive support for bagging memory via mmap.
1141 ------------------------------------------------------------------ */
1142
1143void* VG_(get_memory_from_mmap) ( Int nBytes )
1144{
1145 static UInt tot_alloc = 0;
1146 void* p = VG_(mmap)( 0, nBytes,
1147 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1148 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
1149 if (p != ((void*)(-1))) {
1150 tot_alloc += (UInt)nBytes;
1151 if (0)
1152 VG_(printf)("get_memory_from_mmap: %d tot, %d req\n",
1153 tot_alloc, nBytes);
1154 return p;
1155 }
1156 VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n",
1157 nBytes);
1158 VG_(panic)("vg_get_memory_from_mmap: out of memory! Fatal! Bye!\n");
1159}
1160
1161
1162/*--------------------------------------------------------------------*/
1163/*--- end vg_mylibc.c ---*/
1164/*--------------------------------------------------------------------*/