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