blob: 4b4c8f310fdb4e4eda26ad8520cef1dbb8a499e3 [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
sewardjb48e5002002-05-13 00:16:03 +0000157Bool VG_(kisemptysigset)( vki_ksigset_t* set )
158{
159 Int i;
160 vg_assert(set != NULL);
161 for (i = 0; i < VKI_KNSIG_WORDS; i++)
162 if (set->ws[i] != 0x0) return False;
163 return True;
164}
165
sewardjde4a1d02002-03-22 01:27:54 +0000166Int VG_(ksigaddset)( vki_ksigset_t* set, Int signum )
167{
168 if (set == NULL)
169 return -1;
170 if (signum < 1 && signum > VKI_KNSIG)
171 return -1;
172 signum--;
173 set->ws[signum / VKI_KNSIG_BPW] |= (1 << (signum % VKI_KNSIG_BPW));
174 return 0;
175}
176
177Int VG_(ksigismember) ( vki_ksigset_t* set, Int signum )
178{
179 if (set == NULL)
sewardjb48e5002002-05-13 00:16:03 +0000180 return 0;
sewardjde4a1d02002-03-22 01:27:54 +0000181 if (signum < 1 && signum > VKI_KNSIG)
sewardjb48e5002002-05-13 00:16:03 +0000182 return 0;
sewardjde4a1d02002-03-22 01:27:54 +0000183 signum--;
184 if (1 & ((set->ws[signum / VKI_KNSIG_BPW]) >> (signum % VKI_KNSIG_BPW)))
185 return 1;
186 else
187 return 0;
188}
189
190
sewardjb48e5002002-05-13 00:16:03 +0000191/* Add all signals in src to dst. */
192void VG_(ksigaddset_from_set)( vki_ksigset_t* dst, vki_ksigset_t* src )
193{
194 Int i;
195 vg_assert(dst != NULL && src != NULL);
196 for (i = 0; i < VKI_KNSIG_WORDS; i++)
197 dst->ws[i] |= src->ws[i];
198}
199
200/* Remove all signals in src from dst. */
201void VG_(ksigdelset_from_set)( vki_ksigset_t* dst, vki_ksigset_t* src )
202{
203 Int i;
204 vg_assert(dst != NULL && src != NULL);
205 for (i = 0; i < VKI_KNSIG_WORDS; i++)
206 dst->ws[i] &= ~(src->ws[i]);
207}
208
209
sewardjde4a1d02002-03-22 01:27:54 +0000210/* The functions sigaction, sigprocmask, sigpending and sigsuspend
211 return 0 on success and -1 on error.
212*/
213Int VG_(ksigprocmask)( Int how,
214 const vki_ksigset_t* set,
215 vki_ksigset_t* oldset)
216{
217 Int res
218 = vg_do_syscall4(__NR_rt_sigprocmask,
219 how, (UInt)set, (UInt)oldset,
220 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
221 return VG_(is_kerror)(res) ? -1 : 0;
222}
223
224
225Int VG_(ksigaction) ( Int signum,
226 const vki_ksigaction* act,
227 vki_ksigaction* oldact)
228{
229 Int res
230 = vg_do_syscall4(__NR_rt_sigaction,
231 signum, (UInt)act, (UInt)oldact,
232 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
233 return VG_(is_kerror)(res) ? -1 : 0;
234}
235
236
237Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss )
238{
239 Int res
240 = vg_do_syscall2(__NR_sigaltstack, (UInt)ss, (UInt)oss);
241 return VG_(is_kerror)(res) ? -1 : 0;
242}
243
244
245Int VG_(ksignal)(Int signum, void (*sighandler)(Int))
246{
247 Int res;
248 vki_ksigaction sa;
249 sa.ksa_handler = sighandler;
250 sa.ksa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
251 sa.ksa_restorer = NULL;
252 res = VG_(ksigemptyset)( &sa.ksa_mask );
253 vg_assert(res == 0);
254 res = vg_do_syscall4(__NR_rt_sigaction,
255 signum, (UInt)(&sa), (UInt)NULL,
256 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
257 return VG_(is_kerror)(res) ? -1 : 0;
258}
259
260
261/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000262 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000263 ------------------------------------------------------------------ */
264
265/* Returns -1 on failure. */
266void* VG_(mmap)( void* start, UInt length,
267 UInt prot, UInt flags, UInt fd, UInt offset)
268{
269 Int res;
270 UInt args[6];
271 args[0] = (UInt)start;
272 args[1] = length;
273 args[2] = prot;
274 args[3] = flags;
275 args[4] = fd;
276 args[5] = offset;
277 res = vg_do_syscall1(__NR_mmap, (UInt)(&(args[0])) );
278 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
279}
280
281/* Returns -1 on failure. */
282Int VG_(munmap)( void* start, Int length )
283{
284 Int res = vg_do_syscall2(__NR_munmap, (UInt)start, (UInt)length );
285 return VG_(is_kerror)(res) ? -1 : 0;
286}
287
288void VG_(exit)( Int status )
289{
290 (void)vg_do_syscall1(__NR_exit, (UInt)status );
291 /* Why are we still alive here? */
292 /*NOTREACHED*/
293 vg_assert(2+2 == 5);
294}
295
sewardj2e93c502002-04-12 11:12:52 +0000296/* Returns -1 on error. */
297Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
298{
299 Int res = vg_do_syscall3(__NR_fcntl, fd, cmd, arg);
300 return VG_(is_kerror)(res) ? -1 : res;
301}
302
303/* Returns -1 on error. */
304Int VG_(select)( Int n,
305 vki_fd_set* readfds,
306 vki_fd_set* writefds,
307 vki_fd_set* exceptfds,
308 struct vki_timeval * timeout )
309{
310 Int res;
311 UInt args[5];
312 args[0] = n;
313 args[1] = (UInt)readfds;
314 args[2] = (UInt)writefds;
315 args[3] = (UInt)exceptfds;
316 args[4] = (UInt)timeout;
317 res = vg_do_syscall1(__NR_select, (UInt)(&(args[0])) );
318 return VG_(is_kerror)(res) ? -1 : res;
sewardj2e93c502002-04-12 11:12:52 +0000319}
320
sewardj5f07b662002-04-23 16:52:51 +0000321/* Returns -1 on error, 0 if ok, 1 if interrupted. */
sewardj2e93c502002-04-12 11:12:52 +0000322Int VG_(nanosleep)( const struct vki_timespec *req,
323 struct vki_timespec *rem )
324{
325 Int res;
326 res = vg_do_syscall2(__NR_nanosleep, (UInt)req, (UInt)rem);
327 if (res == -VKI_EINVAL) return -1;
sewardj5f07b662002-04-23 16:52:51 +0000328 if (res == -VKI_EINTR) return 1;
sewardj2e93c502002-04-12 11:12:52 +0000329 return 0;
330}
331
sewardjb3586202002-05-09 17:38:13 +0000332void* VG_(brk) ( void* end_data_segment )
333{
334 Int res;
335 res = vg_do_syscall1(__NR_brk, (UInt)end_data_segment);
336 return (void*)( VG_(is_kerror)(res) ? -1 : res );
337}
338
sewardj2e93c502002-04-12 11:12:52 +0000339
sewardjde4a1d02002-03-22 01:27:54 +0000340/* ---------------------------------------------------------------------
341 printf implementation. The key function, vg_vprintf(), emits chars
342 into a caller-supplied function. Distantly derived from:
343
344 vprintf replacement for Checker.
345 Copyright 1993, 1994, 1995 Tristan Gingold
346 Written September 1993 Tristan Gingold
347 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
348
349 (Checker itself was GPL'd.)
350 ------------------------------------------------------------------ */
351
352
353/* Some flags. */
354#define VG_MSG_SIGNED 1 /* The value is signed. */
355#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
356#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
357
358
359/* Copy a string into the buffer. */
360static void
361myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
362 Bool capitalise )
363{
364# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
365
366 Int i, extra;
367 Int len = VG_(strlen)(str);
368
369 if (width == 0) {
370 for (i = 0; i < len; i++)
371 send(MAYBE_TOUPPER(str[i]));
372 return;
373 }
374
375 if (len > width) {
376 for (i = 0; i < width; i++)
377 send(MAYBE_TOUPPER(str[i]));
378 return;
379 }
380
381 extra = width - len;
382 if (flags & VG_MSG_LJUSTIFY) {
383 for (i = 0; i < extra; i++)
384 send(' ');
385 }
386 for (i = 0; i < len; i++)
387 send(MAYBE_TOUPPER(str[i]));
388 if (!(flags & VG_MSG_LJUSTIFY)) {
389 for (i = 0; i < extra; i++)
390 send(' ');
391 }
392
393# undef MAYBE_TOUPPER
394}
395
396/* Write P into the buffer according to these args:
397 * If SIGN is true, p is a signed.
398 * BASE is the base.
399 * If WITH_ZERO is true, '0' must be added.
400 * WIDTH is the width of the field.
401 */
402static void
403myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
404{
405 Char buf[40];
406 Int ind = 0;
407 Int i;
408 Bool neg = False;
409 Char *digits = "0123456789ABCDEF";
410
411 if (base < 2 || base > 16)
412 return;
413
414 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
415 p = - (Long)p;
416 neg = True;
417 }
418
419 if (p == 0)
420 buf[ind++] = '0';
421 else {
422 while (p > 0) {
423 buf[ind++] = digits[p % base];
424 p /= base;
425 }
426 }
427
428 if (neg)
429 buf[ind++] = '-';
430
431 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
432 for(; ind < width; ind++) {
433 vg_assert(ind < 39);
434 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
435 }
436 }
437
438 /* Reverse copy to buffer. */
439 for (i = ind -1; i >= 0; i--)
440 send(buf[i]);
441
442 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
443 for(; ind < width; ind++)
444 send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
445 }
446}
447
448
449/* A simple vprintf(). */
450void
451VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
452{
453 int i;
454 int flags;
455 int width;
456 Bool is_long;
457
458 /* We assume that vargs has already been initialised by the
459 caller, using va_start, and that the caller will similarly
460 clean up with va_end.
461 */
462
463 for (i = 0; format[i] != 0; i++) {
464 if (format[i] != '%') {
465 send(format[i]);
466 continue;
467 }
468 i++;
469 /* A '%' has been found. Ignore a trailing %. */
470 if (format[i] == 0)
471 break;
472 if (format[i] == '%') {
473 /* `%%' is replaced by `%'. */
474 send('%');
475 continue;
476 }
477 flags = 0;
478 is_long = False;
479 width = 0; /* length of the field. */
480 /* If '-' follows '%', justify on the left. */
481 if (format[i] == '-') {
482 flags |= VG_MSG_LJUSTIFY;
483 i++;
484 }
485 /* If '0' follows '%', pads will be inserted. */
486 if (format[i] == '0') {
487 flags |= VG_MSG_ZJUSTIFY;
488 i++;
489 }
490 /* Compute the field length. */
491 while (format[i] >= '0' && format[i] <= '9') {
492 width *= 10;
493 width += format[i++] - '0';
494 }
495 while (format[i] == 'l') {
496 i++;
497 is_long = True;
498 }
499
500 switch (format[i]) {
501 case 'd': /* %d */
502 flags |= VG_MSG_SIGNED;
503 if (is_long)
504 myvprintf_int64(send, flags, 10, width,
505 (ULong)(va_arg (vargs, Long)));
506 else
507 myvprintf_int64(send, flags, 10, width,
508 (ULong)(va_arg (vargs, Int)));
509 break;
510 case 'u': /* %u */
511 if (is_long)
512 myvprintf_int64(send, flags, 10, width,
513 (ULong)(va_arg (vargs, ULong)));
514 else
515 myvprintf_int64(send, flags, 10, width,
516 (ULong)(va_arg (vargs, UInt)));
517 break;
518 case 'p': /* %p */
519 send('0');
520 send('x');
521 myvprintf_int64(send, flags, 16, width,
522 (ULong)((UInt)va_arg (vargs, void *)));
523 break;
524 case 'x': /* %x */
525 if (is_long)
526 myvprintf_int64(send, flags, 16, width,
527 (ULong)(va_arg (vargs, ULong)));
528 else
529 myvprintf_int64(send, flags, 16, width,
530 (ULong)(va_arg (vargs, UInt)));
531 break;
532 case 'c': /* %c */
533 send(va_arg (vargs, int));
534 break;
535 case 's': case 'S': { /* %s */
536 char *str = va_arg (vargs, char *);
537 if (str == (char*) 0) str = "(null)";
538 myvprintf_str(send, flags, width, str, format[i]=='S');
539 break;
540 }
541 default:
542 break;
543 }
544 }
545}
546
547
548/* A general replacement for printf(). Note that only low-level
549 debugging info should be sent via here. The official route is to
550 to use vg_message(). This interface is deprecated.
551*/
552static char myprintf_buf[100];
553static int n_myprintf_buf;
554
555static void add_to_myprintf_buf ( Char c )
556{
557 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
558 if (VG_(clo_logfile_fd) >= 0)
559 VG_(write)
560 (VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
561 n_myprintf_buf = 0;
562 myprintf_buf[n_myprintf_buf] = 0;
563 }
564 myprintf_buf[n_myprintf_buf++] = c;
565 myprintf_buf[n_myprintf_buf] = 0;
566}
567
568void VG_(printf) ( const char *format, ... )
569{
570 va_list vargs;
571 va_start(vargs,format);
572
573 n_myprintf_buf = 0;
574 myprintf_buf[n_myprintf_buf] = 0;
575 VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
576
577 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0)
578 VG_(write)
579 ( VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
580
581 va_end(vargs);
582}
583
584
585/* A general replacement for sprintf(). */
586static Char* vg_sprintf_ptr;
587
588static void add_to_vg_sprintf_buf ( Char c )
589{
590 *vg_sprintf_ptr++ = c;
591}
592
593void VG_(sprintf) ( Char* buf, Char *format, ... )
594{
595 va_list vargs;
596 va_start(vargs,format);
597
598 vg_sprintf_ptr = buf;
599 VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
600 add_to_vg_sprintf_buf(0);
601
602 va_end(vargs);
603}
604
605
606/* ---------------------------------------------------------------------
607 Misc str* functions.
608 ------------------------------------------------------------------ */
609
610Bool VG_(isspace) ( Char c )
611{
612 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
613}
614
615
616Int VG_(strlen) ( const Char* str )
617{
618 Int i = 0;
619 while (str[i] != 0) i++;
620 return i;
621}
622
623
624Long VG_(atoll) ( Char* str )
625{
626 Bool neg = False;
627 Long n = 0;
628 if (*str == '-') { str++; neg = True; };
629 while (*str >= '0' && *str <= '9') {
630 n = 10*n + (Long)(*str - '0');
631 str++;
632 }
633 if (neg) n = -n;
634 return n;
635}
636
637
638Char* VG_(strcat) ( Char* dest, const Char* src )
639{
640 Char* dest_orig = dest;
641 while (*dest) dest++;
642 while (*src) *dest++ = *src++;
643 *dest = 0;
644 return dest_orig;
645}
646
647
648Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
649{
650 Char* dest_orig = dest;
651 while (*dest) dest++;
652 while (*src && n > 0) { *dest++ = *src++; n--; }
653 *dest = 0;
654 return dest_orig;
655}
656
657
658Char* VG_(strpbrk) ( const Char* s, const Char* accept )
659{
660 const Char* a;
661 while (*s) {
662 a = accept;
663 while (*a)
664 if (*a++ == *s)
665 return (Char *) s;
666 s++;
667 }
668 return NULL;
669}
670
671
672Char* VG_(strcpy) ( Char* dest, const Char* src )
673{
674 Char* dest_orig = dest;
675 while (*src) *dest++ = *src++;
676 *dest = 0;
677 return dest_orig;
678}
679
680
681/* Copy bytes, not overrunning the end of dest and always ensuring
682 zero termination. */
683void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
684{
685 Int i;
686 vg_assert(ndest > 0);
687 i = 0;
688 dest[i] = 0;
689 while (True) {
690 if (src[i] == 0) return;
691 if (i >= ndest-1) return;
692 dest[i] = src[i];
693 i++;
694 dest[i] = 0;
695 }
696}
697
698
699void VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
700{
701 VG_(strncpy_safely)( dest, src, ndest+1 );
702}
703
704
705Int VG_(strcmp) ( const Char* s1, const Char* s2 )
706{
707 while (True) {
708 if (*s1 == 0 && *s2 == 0) return 0;
709 if (*s1 == 0) return -1;
710 if (*s2 == 0) return 1;
711
712 if (*(UChar*)s1 < *(UChar*)s2) return -1;
713 if (*(UChar*)s1 > *(UChar*)s2) return 1;
714
715 s1++; s2++;
716 }
717}
718
719
720Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
721{
722 while (True) {
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++;
731 }
732}
733
734
735Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
736{
737 Int n = 0;
738 while (True) {
739 if (n >= nmax) return 0;
740 if (*s1 == 0 && *s2 == 0) return 0;
741 if (*s1 == 0) return -1;
742 if (*s2 == 0) return 1;
743
744 if (*(UChar*)s1 < *(UChar*)s2) return -1;
745 if (*(UChar*)s1 > *(UChar*)s2) return 1;
746
747 s1++; s2++; n++;
748 }
749}
750
751
752Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
753{
754 Int n = 0;
755 while (True) {
756 if (n >= nmax) return 0;
757 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
758 if (VG_(isspace)(*s1)) return -1;
759 if (VG_(isspace)(*s2)) return 1;
760
761 if (*(UChar*)s1 < *(UChar*)s2) return -1;
762 if (*(UChar*)s1 > *(UChar*)s2) return 1;
763
764 s1++; s2++; n++;
765 }
766}
767
768
769Char* VG_(strstr) ( const Char* haystack, Char* needle )
770{
sewardj3984b852002-05-12 03:00:17 +0000771 Int n;
772 if (haystack == NULL)
773 return NULL;
774 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000775 while (True) {
776 if (haystack[0] == 0)
777 return NULL;
778 if (VG_(strncmp)(haystack, needle, n) == 0)
779 return (Char*)haystack;
780 haystack++;
781 }
782}
783
784
785Char* VG_(strchr) ( const Char* s, Char c )
786{
787 while (True) {
788 if (*s == c) return (Char*)s;
789 if (*s == 0) return NULL;
790 s++;
791 }
792}
793
794
795Char VG_(toupper) ( Char c )
796{
797 if (c >= 'a' && c <= 'z')
798 return c + ('A' - 'a');
799 else
800 return c;
801}
802
803
804Char* VG_(strdup) ( ArenaId aid, const Char* s )
805{
806 Int i;
807 Int len = VG_(strlen)(s) + 1;
808 Char* res = VG_(malloc) (aid, len);
809 for (i = 0; i < len; i++)
810 res[i] = s[i];
811 return res;
812}
813
814
815/* ---------------------------------------------------------------------
816 A simple string matching routine, purloined from Hugs98.
817 `*' matches any sequence of zero or more characters
818 `?' matches any single character exactly
819 `\c' matches the character c only (ignoring special chars)
820 c matches the character c only
821 ------------------------------------------------------------------ */
822
823/* Keep track of recursion depth. */
824static Int recDepth;
825
826static Bool stringMatch_wrk ( Char* pat, Char* str )
827{
828 vg_assert(recDepth >= 0 && recDepth < 500);
829 recDepth++;
830 for (;;) {
831 switch (*pat) {
832 case '\0' : return (*str=='\0');
833 case '*' : do {
834 if (stringMatch_wrk(pat+1,str)) {
835 recDepth--;
836 return True;
837 }
838 } while (*str++);
839 recDepth--;
840 return False;
841 case '?' : if (*str++=='\0') {
842 recDepth--;
843 return False;
844 }
845 pat++;
846 break;
847 case '\\' : if (*++pat == '\0') {
848 recDepth--;
849 return False; /* spurious trailing \ in pattern */
850 }
851 /* falls through to ... */
852 default : if (*pat++ != *str++) {
853 recDepth--;
854 return False;
855 }
856 break;
857 }
858 }
859}
860
861Bool VG_(stringMatch) ( Char* pat, Char* str )
862{
863 Bool b;
864 recDepth = 0;
865 b = stringMatch_wrk ( pat, str );
866 /*
867 VG_(printf)("%s %s %s\n",
868 b?"TRUE ":"FALSE", pat, str);
869 */
870 return b;
871}
872
873
874/* ---------------------------------------------------------------------
875 Assertery.
876 ------------------------------------------------------------------ */
877
878#define EMAIL_ADDR "jseward@acm.org"
879
880void VG_(assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
881{
882 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
883 "valgrind", file, line, fn, expr );
sewardj15a43e12002-04-17 19:35:12 +0000884 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +0000885 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
886 VG_(shutdown_logging)();
sewardjde4a1d02002-03-22 01:27:54 +0000887 VG_(exit)(1);
888}
889
890void VG_(panic) ( Char* str )
891{
892 VG_(printf)("\nvalgrind: the `impossible' happened:\n %s\n", str);
893 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
sewardj15a43e12002-04-17 19:35:12 +0000894 VG_(pp_sched_status)();
sewardjde4a1d02002-03-22 01:27:54 +0000895 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
896 VG_(shutdown_logging)();
sewardjde4a1d02002-03-22 01:27:54 +0000897 VG_(exit)(1);
898}
899
900#undef EMAIL_ADDR
901
902
903/* ---------------------------------------------------------------------
904 Primitive support for reading files.
905 ------------------------------------------------------------------ */
906
907/* Returns -1 on failure. */
908Int VG_(open_read) ( Char* pathname )
909{
910 Int fd;
911 /* VG_(printf)("vg_open_read %s\n", pathname ); */
912
913 /* This gets a segmentation fault if pathname isn't a valid file.
914 I don't know why. It seems like the call to open is getting
915 intercepted and messed with by glibc ... */
916 /* fd = open( pathname, O_RDONLY ); */
917 /* ... so we go direct to the horse's mouth, which seems to work
918 ok: */
919 const int O_RDONLY = 0; /* See /usr/include/bits/fcntl.h */
920 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_RDONLY, 0);
921 /* VG_(printf)("result = %d\n", fd); */
922 if (VG_(is_kerror)(fd)) fd = -1;
923 return fd;
924}
njn4f9c9342002-04-29 16:03:24 +0000925
926/* Returns -1 on failure. */
927static Int VG_(chmod_u_rw) ( Int fd )
928{
929 Int res;
930 const int O_IRUSR_IWUSR = 000600; /* See /usr/include/cpio.h */
931 res = vg_do_syscall2(__NR_fchmod, fd, O_IRUSR_IWUSR);
932 if (VG_(is_kerror)(res)) res = -1;
933 return res;
934}
sewardjde4a1d02002-03-22 01:27:54 +0000935
njn4f9c9342002-04-29 16:03:24 +0000936/* Returns -1 on failure. */
937Int VG_(create_and_write) ( Char* pathname )
938{
939 Int fd;
940
941 const int O_CR_AND_WR_ONLY = 0101; /* See /usr/include/bits/fcntl.h */
942 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_CR_AND_WR_ONLY, 0);
943 /* VG_(printf)("result = %d\n", fd); */
944 if (VG_(is_kerror)(fd)) {
945 fd = -1;
946 } else {
947 VG_(chmod_u_rw)(fd);
948 if (VG_(is_kerror)(fd)) {
949 fd = -1;
950 }
951 }
952 return fd;
953}
954
955/* Returns -1 on failure. */
956Int VG_(open_write) ( Char* pathname )
957{
958 Int fd;
959
960 const int O_WRONLY_AND_TRUNC = 01001; /* See /usr/include/bits/fcntl.h */
961 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_WRONLY_AND_TRUNC, 0);
962 /* VG_(printf)("result = %d\n", fd); */
963 if (VG_(is_kerror)(fd)) {
964 fd = -1;
965 }
966 return fd;
967}
sewardjde4a1d02002-03-22 01:27:54 +0000968
969void VG_(close) ( Int fd )
970{
971 vg_do_syscall1(__NR_close, fd);
972}
973
974
975Int VG_(read) ( Int fd, void* buf, Int count)
976{
977 Int res;
978 /* res = read( fd, buf, count ); */
979 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
980 if (VG_(is_kerror)(res)) res = -1;
981 return res;
982}
983
984Int VG_(write) ( Int fd, void* buf, Int count)
985{
986 Int res;
987 /* res = write( fd, buf, count ); */
988 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
989 if (VG_(is_kerror)(res)) res = -1;
990 return res;
991}
992
sewardjb3586202002-05-09 17:38:13 +0000993Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
994{
995 Int res;
996 res = vg_do_syscall2(__NR_stat, (UInt)file_name, (UInt)buf);
997 return
998 VG_(is_kerror)(res) ? (-1) : 0;
999}
1000
sewardjde4a1d02002-03-22 01:27:54 +00001001/* Misc functions looking for a proper home. */
1002
1003/* We do getenv without libc's help by snooping around in
1004 VG_(client_env) as determined at startup time. */
1005Char* VG_(getenv) ( Char* varname )
1006{
1007 Int i, n;
1008 n = VG_(strlen)(varname);
1009 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1010 Char* s = VG_(client_envp)[i];
1011 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1012 return & s[n+1];
1013 }
1014 }
1015 return NULL;
1016}
1017
1018/* You'd be amazed how many places need to know the current pid. */
1019Int VG_(getpid) ( void )
1020{
1021 Int res;
1022 /* res = getpid(); */
1023 res = vg_do_syscall0(__NR_getpid);
1024 return res;
1025}
1026
sewardje6a25242002-04-21 22:03:07 +00001027/* Return -1 if error, else 0. NOTE does not indicate return code of
1028 child! */
1029Int VG_(system) ( Char* cmd )
1030{
1031 Int pid, res;
1032 void* environ[1] = { NULL };
1033 if (cmd == NULL)
1034 return 1;
1035 pid = vg_do_syscall0(__NR_fork);
1036 if (VG_(is_kerror)(pid))
1037 return -1;
1038 if (pid == 0) {
1039 /* child */
1040 Char* argv[4];
1041 argv[0] = "/bin/sh";
1042 argv[1] = "-c";
1043 argv[2] = cmd;
1044 argv[3] = 0;
1045 (void)vg_do_syscall3(__NR_execve,
1046 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
1047 /* If we're still alive here, execve failed. */
1048 return -1;
1049 } else {
1050 /* parent */
1051 res = vg_do_syscall3(__NR_waitpid, pid, (UInt)NULL, 0);
1052 if (VG_(is_kerror)(res)) {
1053 return -1;
1054 } else {
1055 return 0;
1056 }
1057 }
1058}
1059
1060
sewardjde4a1d02002-03-22 01:27:54 +00001061/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001062 Support for a millisecond-granularity counter using RDTSC.
1063 ------------------------------------------------------------------ */
1064
1065static __inline__ ULong do_rdtsc_insn ( void )
1066{
1067 ULong x;
1068 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1069 return x;
1070}
1071
1072/* 0 = pre-calibration, 1 = calibration, 2 = running */
1073static Int rdtsc_calibration_state = 0;
1074static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1075
1076static struct vki_timeval rdtsc_cal_start_timeval;
1077static struct vki_timeval rdtsc_cal_end_timeval;
1078
1079static ULong rdtsc_cal_start_raw;
1080static ULong rdtsc_cal_end_raw;
1081
1082UInt VG_(read_millisecond_timer) ( void )
1083{
1084 ULong rdtsc_now;
1085 vg_assert(rdtsc_calibration_state == 2);
1086 rdtsc_now = do_rdtsc_insn();
1087 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1088 rdtsc_now -= rdtsc_cal_end_raw;
1089 rdtsc_now /= rdtsc_ticks_per_millisecond;
1090 return (UInt)rdtsc_now;
1091}
1092
1093
1094void VG_(start_rdtsc_calibration) ( void )
1095{
1096 Int res;
1097 vg_assert(rdtsc_calibration_state == 0);
1098 rdtsc_calibration_state = 1;
1099 rdtsc_cal_start_raw = do_rdtsc_insn();
1100 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1101 (UInt)NULL);
1102 vg_assert(!VG_(is_kerror)(res));
1103}
1104
1105void VG_(end_rdtsc_calibration) ( void )
1106{
1107 Int res, loops;
1108 ULong cpu_clock_MHZ;
1109 ULong cal_clock_ticks;
1110 ULong cal_wallclock_microseconds;
1111 ULong wallclock_start_microseconds;
1112 ULong wallclock_end_microseconds;
1113 struct vki_timespec req;
1114 struct vki_timespec rem;
1115
1116 vg_assert(rdtsc_calibration_state == 1);
1117 rdtsc_calibration_state = 2;
1118
1119 /* Try and delay for 20 milliseconds, so that we can at least have
1120 some minimum level of accuracy. */
1121 req.tv_sec = 0;
1122 req.tv_nsec = 20 * 1000 * 1000;
1123 loops = 0;
1124 while (True) {
1125 res = VG_(nanosleep)(&req, &rem);
1126 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1127 if (res == 0)
1128 break;
1129 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1130 break;
1131 req = rem;
1132 loops++;
1133 if (loops > 100)
1134 VG_(panic)("calibration nanosleep loop failed?!");
1135 }
1136
1137 /* Now read both timers, and do the Math. */
1138 rdtsc_cal_end_raw = do_rdtsc_insn();
1139 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1140 (UInt)NULL);
1141
1142 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1143 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1144
1145 wallclock_start_microseconds
1146 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1147 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1148 wallclock_end_microseconds
1149 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1150 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1151 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1152 cal_wallclock_microseconds
1153 = wallclock_end_microseconds - wallclock_start_microseconds;
1154
1155 /* Since we just nanoslept for 20 ms ... */
1156 vg_assert(cal_wallclock_microseconds >= 20000);
1157
1158 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1159 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1160 ticks-per-millisecond value. */
1161 if (0)
1162 VG_(printf)("%lld ticks in %lld microseconds\n",
1163 cal_clock_ticks, cal_wallclock_microseconds );
1164
1165 rdtsc_ticks_per_millisecond
1166 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1167 cpu_clock_MHZ
1168 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1169 if (VG_(clo_verbosity) >= 1)
1170 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1171 (UInt)cpu_clock_MHZ);
1172 if (cpu_clock_MHZ < 100 || cpu_clock_MHZ > 10000)
1173 VG_(panic)("end_rdtsc_calibration: "
1174 "estimated CPU MHz outside range 100 .. 10000");
1175 /* Paranoia about division by zero later. */
1176 vg_assert(rdtsc_ticks_per_millisecond != 0);
1177 if (0)
1178 VG_(printf)("ticks per millisecond %llu\n",
1179 rdtsc_ticks_per_millisecond);
1180}
1181
1182
1183
1184/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001185 Primitive support for bagging memory via mmap.
1186 ------------------------------------------------------------------ */
1187
1188void* VG_(get_memory_from_mmap) ( Int nBytes )
1189{
1190 static UInt tot_alloc = 0;
1191 void* p = VG_(mmap)( 0, nBytes,
1192 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1193 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
1194 if (p != ((void*)(-1))) {
1195 tot_alloc += (UInt)nBytes;
1196 if (0)
1197 VG_(printf)("get_memory_from_mmap: %d tot, %d req\n",
1198 tot_alloc, nBytes);
1199 return p;
1200 }
1201 VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n",
1202 nBytes);
1203 VG_(panic)("vg_get_memory_from_mmap: out of memory! Fatal! Bye!\n");
1204}
1205
1206
1207/*--------------------------------------------------------------------*/
1208/*--- end vg_mylibc.c ---*/
1209/*--------------------------------------------------------------------*/