blob: 2ba0753d32fea82c4745a06f17d0878fa6edbac1 [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
14 Julian_Seward@muraroa.demon.co.uk
15
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 02111-1307, USA.
30
31 The GNU General Public License is contained in the file LICENSE.
32*/
33
34#include "vg_include.h"
35
36
37
38/* ---------------------------------------------------------------------
39 Really Actually DO system calls.
40 ------------------------------------------------------------------ */
41
42/* Ripped off from /usr/include/asm/unistd.h. */
43
44static
45UInt vg_do_syscall0 ( UInt syscallno )
46{
47 UInt __res;
48 __asm__ volatile ("int $0x80"
49 : "=a" (__res)
50 : "0" (syscallno) );
51 return __res;
52}
53
54
55static
56UInt vg_do_syscall1 ( UInt syscallno, UInt arg1 )
57{
58 UInt __res;
59 __asm__ volatile ("int $0x80"
60 : "=a" (__res)
61 : "0" (syscallno),
62 "b" (arg1) );
63 return __res;
64}
65
66
67static
68UInt vg_do_syscall2 ( UInt syscallno,
69 UInt arg1, UInt arg2 )
70{
71 UInt __res;
72 __asm__ volatile ("int $0x80"
73 : "=a" (__res)
74 : "0" (syscallno),
75 "b" (arg1),
76 "c" (arg2) );
77 return __res;
78}
79
80
81static
82UInt vg_do_syscall3 ( UInt syscallno,
83 UInt arg1, UInt arg2, UInt arg3 )
84{
85 UInt __res;
86 __asm__ volatile ("int $0x80"
87 : "=a" (__res)
88 : "0" (syscallno),
89 "b" (arg1),
90 "c" (arg2),
91 "d" (arg3) );
92 return __res;
93}
94
95
96static
97UInt vg_do_syscall4 ( UInt syscallno,
98 UInt arg1, UInt arg2, UInt arg3, UInt arg4 )
99{
100 UInt __res;
101 __asm__ volatile ("int $0x80"
102 : "=a" (__res)
103 : "0" (syscallno),
104 "b" (arg1),
105 "c" (arg2),
106 "d" (arg3),
107 "S" (arg4) );
108 return __res;
109}
110
111
112#if 0
113static
114UInt vg_do_syscall5 ( UInt syscallno,
115 UInt arg1, UInt arg2, UInt arg3, UInt arg4,
116 UInt arg5 )
117{
118 UInt __res;
119 __asm__ volatile ("int $0x80"
120 : "=a" (__res)
121 : "0" (syscallno),
122 "b" (arg1),
123 "c" (arg2),
124 "d" (arg3),
125 "S" (arg4),
126 "D" (arg5) );
127 return __res;
128}
129#endif
130
131/* ---------------------------------------------------------------------
132 Wrappers around system calls, and other stuff, to do with signals.
133 ------------------------------------------------------------------ */
134
135/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
136 success and -1 on error.
137*/
138Int VG_(ksigfillset)( vki_ksigset_t* set )
139{
140 Int i;
141 if (set == NULL)
142 return -1;
143 for (i = 0; i < VKI_KNSIG_WORDS; i++)
144 set->ws[i] = 0xFFFFFFFF;
145 return 0;
146}
147
148Int VG_(ksigemptyset)( vki_ksigset_t* set )
149{
150 Int i;
151 if (set == NULL)
152 return -1;
153 for (i = 0; i < VKI_KNSIG_WORDS; i++)
154 set->ws[i] = 0x0;
155 return 0;
156}
157
158Int VG_(ksigaddset)( vki_ksigset_t* set, Int signum )
159{
160 if (set == NULL)
161 return -1;
162 if (signum < 1 && signum > VKI_KNSIG)
163 return -1;
164 signum--;
165 set->ws[signum / VKI_KNSIG_BPW] |= (1 << (signum % VKI_KNSIG_BPW));
166 return 0;
167}
168
169Int VG_(ksigismember) ( vki_ksigset_t* set, Int signum )
170{
171 if (set == NULL)
172 return -1;
173 if (signum < 1 && signum > VKI_KNSIG)
174 return -1;
175 signum--;
176 if (1 & ((set->ws[signum / VKI_KNSIG_BPW]) >> (signum % VKI_KNSIG_BPW)))
177 return 1;
178 else
179 return 0;
180}
181
182
183/* The functions sigaction, sigprocmask, sigpending and sigsuspend
184 return 0 on success and -1 on error.
185*/
186Int VG_(ksigprocmask)( Int how,
187 const vki_ksigset_t* set,
188 vki_ksigset_t* oldset)
189{
190 Int res
191 = vg_do_syscall4(__NR_rt_sigprocmask,
192 how, (UInt)set, (UInt)oldset,
193 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
194 return VG_(is_kerror)(res) ? -1 : 0;
195}
196
197
198Int VG_(ksigaction) ( Int signum,
199 const vki_ksigaction* act,
200 vki_ksigaction* oldact)
201{
202 Int res
203 = vg_do_syscall4(__NR_rt_sigaction,
204 signum, (UInt)act, (UInt)oldact,
205 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
206 return VG_(is_kerror)(res) ? -1 : 0;
207}
208
209
210Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss )
211{
212 Int res
213 = vg_do_syscall2(__NR_sigaltstack, (UInt)ss, (UInt)oss);
214 return VG_(is_kerror)(res) ? -1 : 0;
215}
216
217
218Int VG_(ksignal)(Int signum, void (*sighandler)(Int))
219{
220 Int res;
221 vki_ksigaction sa;
222 sa.ksa_handler = sighandler;
223 sa.ksa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
224 sa.ksa_restorer = NULL;
225 res = VG_(ksigemptyset)( &sa.ksa_mask );
226 vg_assert(res == 0);
227 res = vg_do_syscall4(__NR_rt_sigaction,
228 signum, (UInt)(&sa), (UInt)NULL,
229 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
230 return VG_(is_kerror)(res) ? -1 : 0;
231}
232
233
234/* ---------------------------------------------------------------------
235 mmap/munmap, exit
236 ------------------------------------------------------------------ */
237
238/* Returns -1 on failure. */
239void* VG_(mmap)( void* start, UInt length,
240 UInt prot, UInt flags, UInt fd, UInt offset)
241{
242 Int res;
243 UInt args[6];
244 args[0] = (UInt)start;
245 args[1] = length;
246 args[2] = prot;
247 args[3] = flags;
248 args[4] = fd;
249 args[5] = offset;
250 res = vg_do_syscall1(__NR_mmap, (UInt)(&(args[0])) );
251 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
252}
253
254/* Returns -1 on failure. */
255Int VG_(munmap)( void* start, Int length )
256{
257 Int res = vg_do_syscall2(__NR_munmap, (UInt)start, (UInt)length );
258 return VG_(is_kerror)(res) ? -1 : 0;
259}
260
261void VG_(exit)( Int status )
262{
263 (void)vg_do_syscall1(__NR_exit, (UInt)status );
264 /* Why are we still alive here? */
265 /*NOTREACHED*/
266 vg_assert(2+2 == 5);
267}
268
269/* ---------------------------------------------------------------------
270 printf implementation. The key function, vg_vprintf(), emits chars
271 into a caller-supplied function. Distantly derived from:
272
273 vprintf replacement for Checker.
274 Copyright 1993, 1994, 1995 Tristan Gingold
275 Written September 1993 Tristan Gingold
276 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
277
278 (Checker itself was GPL'd.)
279 ------------------------------------------------------------------ */
280
281
282/* Some flags. */
283#define VG_MSG_SIGNED 1 /* The value is signed. */
284#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
285#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
286
287
288/* Copy a string into the buffer. */
289static void
290myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
291 Bool capitalise )
292{
293# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
294
295 Int i, extra;
296 Int len = VG_(strlen)(str);
297
298 if (width == 0) {
299 for (i = 0; i < len; i++)
300 send(MAYBE_TOUPPER(str[i]));
301 return;
302 }
303
304 if (len > width) {
305 for (i = 0; i < width; i++)
306 send(MAYBE_TOUPPER(str[i]));
307 return;
308 }
309
310 extra = width - len;
311 if (flags & VG_MSG_LJUSTIFY) {
312 for (i = 0; i < extra; i++)
313 send(' ');
314 }
315 for (i = 0; i < len; i++)
316 send(MAYBE_TOUPPER(str[i]));
317 if (!(flags & VG_MSG_LJUSTIFY)) {
318 for (i = 0; i < extra; i++)
319 send(' ');
320 }
321
322# undef MAYBE_TOUPPER
323}
324
325/* Write P into the buffer according to these args:
326 * If SIGN is true, p is a signed.
327 * BASE is the base.
328 * If WITH_ZERO is true, '0' must be added.
329 * WIDTH is the width of the field.
330 */
331static void
332myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
333{
334 Char buf[40];
335 Int ind = 0;
336 Int i;
337 Bool neg = False;
338 Char *digits = "0123456789ABCDEF";
339
340 if (base < 2 || base > 16)
341 return;
342
343 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
344 p = - (Long)p;
345 neg = True;
346 }
347
348 if (p == 0)
349 buf[ind++] = '0';
350 else {
351 while (p > 0) {
352 buf[ind++] = digits[p % base];
353 p /= base;
354 }
355 }
356
357 if (neg)
358 buf[ind++] = '-';
359
360 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
361 for(; ind < width; ind++) {
362 vg_assert(ind < 39);
363 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
364 }
365 }
366
367 /* Reverse copy to buffer. */
368 for (i = ind -1; i >= 0; i--)
369 send(buf[i]);
370
371 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
372 for(; ind < width; ind++)
373 send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
374 }
375}
376
377
378/* A simple vprintf(). */
379void
380VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
381{
382 int i;
383 int flags;
384 int width;
385 Bool is_long;
386
387 /* We assume that vargs has already been initialised by the
388 caller, using va_start, and that the caller will similarly
389 clean up with va_end.
390 */
391
392 for (i = 0; format[i] != 0; i++) {
393 if (format[i] != '%') {
394 send(format[i]);
395 continue;
396 }
397 i++;
398 /* A '%' has been found. Ignore a trailing %. */
399 if (format[i] == 0)
400 break;
401 if (format[i] == '%') {
402 /* `%%' is replaced by `%'. */
403 send('%');
404 continue;
405 }
406 flags = 0;
407 is_long = False;
408 width = 0; /* length of the field. */
409 /* If '-' follows '%', justify on the left. */
410 if (format[i] == '-') {
411 flags |= VG_MSG_LJUSTIFY;
412 i++;
413 }
414 /* If '0' follows '%', pads will be inserted. */
415 if (format[i] == '0') {
416 flags |= VG_MSG_ZJUSTIFY;
417 i++;
418 }
419 /* Compute the field length. */
420 while (format[i] >= '0' && format[i] <= '9') {
421 width *= 10;
422 width += format[i++] - '0';
423 }
424 while (format[i] == 'l') {
425 i++;
426 is_long = True;
427 }
428
429 switch (format[i]) {
430 case 'd': /* %d */
431 flags |= VG_MSG_SIGNED;
432 if (is_long)
433 myvprintf_int64(send, flags, 10, width,
434 (ULong)(va_arg (vargs, Long)));
435 else
436 myvprintf_int64(send, flags, 10, width,
437 (ULong)(va_arg (vargs, Int)));
438 break;
439 case 'u': /* %u */
440 if (is_long)
441 myvprintf_int64(send, flags, 10, width,
442 (ULong)(va_arg (vargs, ULong)));
443 else
444 myvprintf_int64(send, flags, 10, width,
445 (ULong)(va_arg (vargs, UInt)));
446 break;
447 case 'p': /* %p */
448 send('0');
449 send('x');
450 myvprintf_int64(send, flags, 16, width,
451 (ULong)((UInt)va_arg (vargs, void *)));
452 break;
453 case 'x': /* %x */
454 if (is_long)
455 myvprintf_int64(send, flags, 16, width,
456 (ULong)(va_arg (vargs, ULong)));
457 else
458 myvprintf_int64(send, flags, 16, width,
459 (ULong)(va_arg (vargs, UInt)));
460 break;
461 case 'c': /* %c */
462 send(va_arg (vargs, int));
463 break;
464 case 's': case 'S': { /* %s */
465 char *str = va_arg (vargs, char *);
466 if (str == (char*) 0) str = "(null)";
467 myvprintf_str(send, flags, width, str, format[i]=='S');
468 break;
469 }
470 default:
471 break;
472 }
473 }
474}
475
476
477/* A general replacement for printf(). Note that only low-level
478 debugging info should be sent via here. The official route is to
479 to use vg_message(). This interface is deprecated.
480*/
481static char myprintf_buf[100];
482static int n_myprintf_buf;
483
484static void add_to_myprintf_buf ( Char c )
485{
486 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
487 if (VG_(clo_logfile_fd) >= 0)
488 VG_(write)
489 (VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
490 n_myprintf_buf = 0;
491 myprintf_buf[n_myprintf_buf] = 0;
492 }
493 myprintf_buf[n_myprintf_buf++] = c;
494 myprintf_buf[n_myprintf_buf] = 0;
495}
496
497void VG_(printf) ( const char *format, ... )
498{
499 va_list vargs;
500 va_start(vargs,format);
501
502 n_myprintf_buf = 0;
503 myprintf_buf[n_myprintf_buf] = 0;
504 VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
505
506 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0)
507 VG_(write)
508 ( VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
509
510 va_end(vargs);
511}
512
513
514/* A general replacement for sprintf(). */
515static Char* vg_sprintf_ptr;
516
517static void add_to_vg_sprintf_buf ( Char c )
518{
519 *vg_sprintf_ptr++ = c;
520}
521
522void VG_(sprintf) ( Char* buf, Char *format, ... )
523{
524 va_list vargs;
525 va_start(vargs,format);
526
527 vg_sprintf_ptr = buf;
528 VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
529 add_to_vg_sprintf_buf(0);
530
531 va_end(vargs);
532}
533
534
535/* ---------------------------------------------------------------------
536 Misc str* functions.
537 ------------------------------------------------------------------ */
538
539Bool VG_(isspace) ( Char c )
540{
541 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
542}
543
544
545Int VG_(strlen) ( const Char* str )
546{
547 Int i = 0;
548 while (str[i] != 0) i++;
549 return i;
550}
551
552
553Long VG_(atoll) ( Char* str )
554{
555 Bool neg = False;
556 Long n = 0;
557 if (*str == '-') { str++; neg = True; };
558 while (*str >= '0' && *str <= '9') {
559 n = 10*n + (Long)(*str - '0');
560 str++;
561 }
562 if (neg) n = -n;
563 return n;
564}
565
566
567Char* VG_(strcat) ( Char* dest, const Char* src )
568{
569 Char* dest_orig = dest;
570 while (*dest) dest++;
571 while (*src) *dest++ = *src++;
572 *dest = 0;
573 return dest_orig;
574}
575
576
577Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
578{
579 Char* dest_orig = dest;
580 while (*dest) dest++;
581 while (*src && n > 0) { *dest++ = *src++; n--; }
582 *dest = 0;
583 return dest_orig;
584}
585
586
587Char* VG_(strpbrk) ( const Char* s, const Char* accept )
588{
589 const Char* a;
590 while (*s) {
591 a = accept;
592 while (*a)
593 if (*a++ == *s)
594 return (Char *) s;
595 s++;
596 }
597 return NULL;
598}
599
600
601Char* VG_(strcpy) ( Char* dest, const Char* src )
602{
603 Char* dest_orig = dest;
604 while (*src) *dest++ = *src++;
605 *dest = 0;
606 return dest_orig;
607}
608
609
610/* Copy bytes, not overrunning the end of dest and always ensuring
611 zero termination. */
612void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
613{
614 Int i;
615 vg_assert(ndest > 0);
616 i = 0;
617 dest[i] = 0;
618 while (True) {
619 if (src[i] == 0) return;
620 if (i >= ndest-1) return;
621 dest[i] = src[i];
622 i++;
623 dest[i] = 0;
624 }
625}
626
627
628void VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
629{
630 VG_(strncpy_safely)( dest, src, ndest+1 );
631}
632
633
634Int VG_(strcmp) ( const Char* s1, const Char* s2 )
635{
636 while (True) {
637 if (*s1 == 0 && *s2 == 0) return 0;
638 if (*s1 == 0) return -1;
639 if (*s2 == 0) return 1;
640
641 if (*(UChar*)s1 < *(UChar*)s2) return -1;
642 if (*(UChar*)s1 > *(UChar*)s2) return 1;
643
644 s1++; s2++;
645 }
646}
647
648
649Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
650{
651 while (True) {
652 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
653 if (VG_(isspace)(*s1)) return -1;
654 if (VG_(isspace)(*s2)) return 1;
655
656 if (*(UChar*)s1 < *(UChar*)s2) return -1;
657 if (*(UChar*)s1 > *(UChar*)s2) return 1;
658
659 s1++; s2++;
660 }
661}
662
663
664Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
665{
666 Int n = 0;
667 while (True) {
668 if (n >= nmax) return 0;
669 if (*s1 == 0 && *s2 == 0) return 0;
670 if (*s1 == 0) return -1;
671 if (*s2 == 0) return 1;
672
673 if (*(UChar*)s1 < *(UChar*)s2) return -1;
674 if (*(UChar*)s1 > *(UChar*)s2) return 1;
675
676 s1++; s2++; n++;
677 }
678}
679
680
681Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
682{
683 Int n = 0;
684 while (True) {
685 if (n >= nmax) return 0;
686 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
687 if (VG_(isspace)(*s1)) return -1;
688 if (VG_(isspace)(*s2)) return 1;
689
690 if (*(UChar*)s1 < *(UChar*)s2) return -1;
691 if (*(UChar*)s1 > *(UChar*)s2) return 1;
692
693 s1++; s2++; n++;
694 }
695}
696
697
698Char* VG_(strstr) ( const Char* haystack, Char* needle )
699{
700 Int n = VG_(strlen)(needle);
701 while (True) {
702 if (haystack[0] == 0)
703 return NULL;
704 if (VG_(strncmp)(haystack, needle, n) == 0)
705 return (Char*)haystack;
706 haystack++;
707 }
708}
709
710
711Char* VG_(strchr) ( const Char* s, Char c )
712{
713 while (True) {
714 if (*s == c) return (Char*)s;
715 if (*s == 0) return NULL;
716 s++;
717 }
718}
719
720
721Char VG_(toupper) ( Char c )
722{
723 if (c >= 'a' && c <= 'z')
724 return c + ('A' - 'a');
725 else
726 return c;
727}
728
729
730Char* VG_(strdup) ( ArenaId aid, const Char* s )
731{
732 Int i;
733 Int len = VG_(strlen)(s) + 1;
734 Char* res = VG_(malloc) (aid, len);
735 for (i = 0; i < len; i++)
736 res[i] = s[i];
737 return res;
738}
739
740
741/* ---------------------------------------------------------------------
742 A simple string matching routine, purloined from Hugs98.
743 `*' matches any sequence of zero or more characters
744 `?' matches any single character exactly
745 `\c' matches the character c only (ignoring special chars)
746 c matches the character c only
747 ------------------------------------------------------------------ */
748
749/* Keep track of recursion depth. */
750static Int recDepth;
751
752static Bool stringMatch_wrk ( Char* pat, Char* str )
753{
754 vg_assert(recDepth >= 0 && recDepth < 500);
755 recDepth++;
756 for (;;) {
757 switch (*pat) {
758 case '\0' : return (*str=='\0');
759 case '*' : do {
760 if (stringMatch_wrk(pat+1,str)) {
761 recDepth--;
762 return True;
763 }
764 } while (*str++);
765 recDepth--;
766 return False;
767 case '?' : if (*str++=='\0') {
768 recDepth--;
769 return False;
770 }
771 pat++;
772 break;
773 case '\\' : if (*++pat == '\0') {
774 recDepth--;
775 return False; /* spurious trailing \ in pattern */
776 }
777 /* falls through to ... */
778 default : if (*pat++ != *str++) {
779 recDepth--;
780 return False;
781 }
782 break;
783 }
784 }
785}
786
787Bool VG_(stringMatch) ( Char* pat, Char* str )
788{
789 Bool b;
790 recDepth = 0;
791 b = stringMatch_wrk ( pat, str );
792 /*
793 VG_(printf)("%s %s %s\n",
794 b?"TRUE ":"FALSE", pat, str);
795 */
796 return b;
797}
798
799
800/* ---------------------------------------------------------------------
801 Assertery.
802 ------------------------------------------------------------------ */
803
804#define EMAIL_ADDR "jseward@acm.org"
805
806void VG_(assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
807{
808 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
809 "valgrind", file, line, fn, expr );
810 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
811 VG_(shutdown_logging)();
812 /* vg_restore_SIGABRT(); */
813 VG_(exit)(1);
814}
815
816void VG_(panic) ( Char* str )
817{
818 VG_(printf)("\nvalgrind: the `impossible' happened:\n %s\n", str);
819 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
820 VG_(printf)("Please report this bug to me at: %s\n\n", EMAIL_ADDR);
821 VG_(shutdown_logging)();
822 /* vg_restore_SIGABRT(); */
823 VG_(exit)(1);
824}
825
826#undef EMAIL_ADDR
827
828
829/* ---------------------------------------------------------------------
830 Primitive support for reading files.
831 ------------------------------------------------------------------ */
832
833/* Returns -1 on failure. */
834Int VG_(open_read) ( Char* pathname )
835{
836 Int fd;
837 /* VG_(printf)("vg_open_read %s\n", pathname ); */
838
839 /* This gets a segmentation fault if pathname isn't a valid file.
840 I don't know why. It seems like the call to open is getting
841 intercepted and messed with by glibc ... */
842 /* fd = open( pathname, O_RDONLY ); */
843 /* ... so we go direct to the horse's mouth, which seems to work
844 ok: */
845 const int O_RDONLY = 0; /* See /usr/include/bits/fcntl.h */
846 fd = vg_do_syscall3(__NR_open, (UInt)pathname, O_RDONLY, 0);
847 /* VG_(printf)("result = %d\n", fd); */
848 if (VG_(is_kerror)(fd)) fd = -1;
849 return fd;
850}
851
852
853void VG_(close) ( Int fd )
854{
855 vg_do_syscall1(__NR_close, fd);
856}
857
858
859Int VG_(read) ( Int fd, void* buf, Int count)
860{
861 Int res;
862 /* res = read( fd, buf, count ); */
863 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
864 if (VG_(is_kerror)(res)) res = -1;
865 return res;
866}
867
868Int VG_(write) ( Int fd, void* buf, Int count)
869{
870 Int res;
871 /* res = write( fd, buf, count ); */
872 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
873 if (VG_(is_kerror)(res)) res = -1;
874 return res;
875}
876
877/* Misc functions looking for a proper home. */
878
879/* We do getenv without libc's help by snooping around in
880 VG_(client_env) as determined at startup time. */
881Char* VG_(getenv) ( Char* varname )
882{
883 Int i, n;
884 n = VG_(strlen)(varname);
885 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
886 Char* s = VG_(client_envp)[i];
887 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
888 return & s[n+1];
889 }
890 }
891 return NULL;
892}
893
894/* You'd be amazed how many places need to know the current pid. */
895Int VG_(getpid) ( void )
896{
897 Int res;
898 /* res = getpid(); */
899 res = vg_do_syscall0(__NR_getpid);
900 return res;
901}
902
903
904/* ---------------------------------------------------------------------
905 Primitive support for bagging memory via mmap.
906 ------------------------------------------------------------------ */
907
908void* VG_(get_memory_from_mmap) ( Int nBytes )
909{
910 static UInt tot_alloc = 0;
911 void* p = VG_(mmap)( 0, nBytes,
912 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
913 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
914 if (p != ((void*)(-1))) {
915 tot_alloc += (UInt)nBytes;
916 if (0)
917 VG_(printf)("get_memory_from_mmap: %d tot, %d req\n",
918 tot_alloc, nBytes);
919 return p;
920 }
921 VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n",
922 nBytes);
923 VG_(panic)("vg_get_memory_from_mmap: out of memory! Fatal! Bye!\n");
924}
925
926
927/*--------------------------------------------------------------------*/
928/*--- end vg_mylibc.c ---*/
929/*--------------------------------------------------------------------*/