blob: 7eab2f7b708c6872cc1d4bfc7b218dd2a243262b [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
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
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;
njn25e49d8e72002-09-23 09:36:25 +0000180 if (signum < 1 || signum > VKI_KNSIG)
sewardjde4a1d02002-03-22 01:27:54 +0000181 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;
njn25e49d8e72002-09-23 09:36:25 +0000191 if (signum < 1 || signum > VKI_KNSIG)
sewardj018f7622002-05-15 21:13:39 +0000192 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;
njn25e49d8e72002-09-23 09:36:25 +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
sewardjdcaf3122002-09-30 23:12:33 +0000283Int VG_(kkill)( Int pid, Int signo )
sewardj018f7622002-05-15 21:13:39 +0000284{
285 Int res = vg_do_syscall2(__NR_kill, pid, signo);
286 return VG_(is_kerror)(res) ? -1 : 0;
287}
288
289
sewardjdcaf3122002-09-30 23:12:33 +0000290Int VG_(ksigpending) ( vki_ksigset_t* set )
sewardjefbfcdf2002-06-19 17:35:45 +0000291{
292 Int res = vg_do_syscall1(__NR_sigpending, (UInt)set);
293 return VG_(is_kerror)(res) ? -1 : 0;
294}
295
296
sewardjde4a1d02002-03-22 01:27:54 +0000297/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000298 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000299 ------------------------------------------------------------------ */
300
301/* Returns -1 on failure. */
302void* VG_(mmap)( void* start, UInt length,
303 UInt prot, UInt flags, UInt fd, UInt offset)
304{
305 Int res;
306 UInt args[6];
307 args[0] = (UInt)start;
308 args[1] = length;
309 args[2] = prot;
310 args[3] = flags;
311 args[4] = fd;
312 args[5] = offset;
313 res = vg_do_syscall1(__NR_mmap, (UInt)(&(args[0])) );
314 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
315}
316
317/* Returns -1 on failure. */
318Int VG_(munmap)( void* start, Int length )
319{
320 Int res = vg_do_syscall2(__NR_munmap, (UInt)start, (UInt)length );
321 return VG_(is_kerror)(res) ? -1 : 0;
322}
323
324void VG_(exit)( Int status )
325{
326 (void)vg_do_syscall1(__NR_exit, (UInt)status );
327 /* Why are we still alive here? */
328 /*NOTREACHED*/
329 vg_assert(2+2 == 5);
330}
331
sewardj2e93c502002-04-12 11:12:52 +0000332/* Returns -1 on error. */
333Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
334{
335 Int res = vg_do_syscall3(__NR_fcntl, fd, cmd, arg);
336 return VG_(is_kerror)(res) ? -1 : res;
337}
338
339/* Returns -1 on error. */
340Int VG_(select)( Int n,
341 vki_fd_set* readfds,
342 vki_fd_set* writefds,
343 vki_fd_set* exceptfds,
344 struct vki_timeval * timeout )
345{
346 Int res;
347 UInt args[5];
348 args[0] = n;
349 args[1] = (UInt)readfds;
350 args[2] = (UInt)writefds;
351 args[3] = (UInt)exceptfds;
352 args[4] = (UInt)timeout;
353 res = vg_do_syscall1(__NR_select, (UInt)(&(args[0])) );
354 return VG_(is_kerror)(res) ? -1 : res;
sewardj2e93c502002-04-12 11:12:52 +0000355}
356
sewardj5f07b662002-04-23 16:52:51 +0000357/* Returns -1 on error, 0 if ok, 1 if interrupted. */
sewardj2e93c502002-04-12 11:12:52 +0000358Int VG_(nanosleep)( const struct vki_timespec *req,
359 struct vki_timespec *rem )
360{
361 Int res;
362 res = vg_do_syscall2(__NR_nanosleep, (UInt)req, (UInt)rem);
363 if (res == -VKI_EINVAL) return -1;
sewardj5f07b662002-04-23 16:52:51 +0000364 if (res == -VKI_EINTR) return 1;
sewardj2e93c502002-04-12 11:12:52 +0000365 return 0;
366}
367
sewardjb3586202002-05-09 17:38:13 +0000368void* VG_(brk) ( void* end_data_segment )
369{
370 Int res;
371 res = vg_do_syscall1(__NR_brk, (UInt)end_data_segment);
372 return (void*)( VG_(is_kerror)(res) ? -1 : res );
373}
374
sewardj2e93c502002-04-12 11:12:52 +0000375
sewardjde4a1d02002-03-22 01:27:54 +0000376/* ---------------------------------------------------------------------
377 printf implementation. The key function, vg_vprintf(), emits chars
378 into a caller-supplied function. Distantly derived from:
379
380 vprintf replacement for Checker.
381 Copyright 1993, 1994, 1995 Tristan Gingold
382 Written September 1993 Tristan Gingold
383 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
384
385 (Checker itself was GPL'd.)
386 ------------------------------------------------------------------ */
387
388
389/* Some flags. */
390#define VG_MSG_SIGNED 1 /* The value is signed. */
391#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
392#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
393
394
395/* Copy a string into the buffer. */
396static void
397myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
398 Bool capitalise )
399{
400# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
401
402 Int i, extra;
403 Int len = VG_(strlen)(str);
404
405 if (width == 0) {
406 for (i = 0; i < len; i++)
407 send(MAYBE_TOUPPER(str[i]));
408 return;
409 }
410
411 if (len > width) {
412 for (i = 0; i < width; i++)
413 send(MAYBE_TOUPPER(str[i]));
414 return;
415 }
416
417 extra = width - len;
418 if (flags & VG_MSG_LJUSTIFY) {
419 for (i = 0; i < extra; i++)
420 send(' ');
421 }
422 for (i = 0; i < len; i++)
423 send(MAYBE_TOUPPER(str[i]));
424 if (!(flags & VG_MSG_LJUSTIFY)) {
425 for (i = 0; i < extra; i++)
426 send(' ');
427 }
428
429# undef MAYBE_TOUPPER
430}
431
432/* Write P into the buffer according to these args:
433 * If SIGN is true, p is a signed.
434 * BASE is the base.
435 * If WITH_ZERO is true, '0' must be added.
436 * WIDTH is the width of the field.
437 */
438static void
439myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
440{
441 Char buf[40];
442 Int ind = 0;
443 Int i;
444 Bool neg = False;
445 Char *digits = "0123456789ABCDEF";
446
447 if (base < 2 || base > 16)
448 return;
449
450 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
451 p = - (Long)p;
452 neg = True;
453 }
454
455 if (p == 0)
456 buf[ind++] = '0';
457 else {
458 while (p > 0) {
459 buf[ind++] = digits[p % base];
460 p /= base;
461 }
462 }
463
464 if (neg)
465 buf[ind++] = '-';
466
467 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
468 for(; ind < width; ind++) {
469 vg_assert(ind < 39);
470 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
471 }
472 }
473
474 /* Reverse copy to buffer. */
475 for (i = ind -1; i >= 0; i--)
476 send(buf[i]);
477
478 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
479 for(; ind < width; ind++)
480 send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
481 }
482}
483
484
485/* A simple vprintf(). */
486void
487VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
488{
489 int i;
490 int flags;
491 int width;
492 Bool is_long;
493
494 /* We assume that vargs has already been initialised by the
495 caller, using va_start, and that the caller will similarly
496 clean up with va_end.
497 */
498
499 for (i = 0; format[i] != 0; i++) {
500 if (format[i] != '%') {
501 send(format[i]);
502 continue;
503 }
504 i++;
505 /* A '%' has been found. Ignore a trailing %. */
506 if (format[i] == 0)
507 break;
508 if (format[i] == '%') {
509 /* `%%' is replaced by `%'. */
510 send('%');
511 continue;
512 }
513 flags = 0;
514 is_long = False;
515 width = 0; /* length of the field. */
516 /* If '-' follows '%', justify on the left. */
517 if (format[i] == '-') {
518 flags |= VG_MSG_LJUSTIFY;
519 i++;
520 }
521 /* If '0' follows '%', pads will be inserted. */
522 if (format[i] == '0') {
523 flags |= VG_MSG_ZJUSTIFY;
524 i++;
525 }
526 /* Compute the field length. */
527 while (format[i] >= '0' && format[i] <= '9') {
528 width *= 10;
529 width += format[i++] - '0';
530 }
531 while (format[i] == 'l') {
532 i++;
533 is_long = True;
534 }
535
536 switch (format[i]) {
537 case 'd': /* %d */
538 flags |= VG_MSG_SIGNED;
539 if (is_long)
540 myvprintf_int64(send, flags, 10, width,
541 (ULong)(va_arg (vargs, Long)));
542 else
543 myvprintf_int64(send, flags, 10, width,
544 (ULong)(va_arg (vargs, Int)));
545 break;
546 case 'u': /* %u */
547 if (is_long)
548 myvprintf_int64(send, flags, 10, width,
549 (ULong)(va_arg (vargs, ULong)));
550 else
551 myvprintf_int64(send, flags, 10, width,
552 (ULong)(va_arg (vargs, UInt)));
553 break;
554 case 'p': /* %p */
555 send('0');
556 send('x');
557 myvprintf_int64(send, flags, 16, width,
558 (ULong)((UInt)va_arg (vargs, void *)));
559 break;
560 case 'x': /* %x */
561 if (is_long)
562 myvprintf_int64(send, flags, 16, width,
563 (ULong)(va_arg (vargs, ULong)));
564 else
565 myvprintf_int64(send, flags, 16, width,
566 (ULong)(va_arg (vargs, UInt)));
567 break;
568 case 'c': /* %c */
569 send(va_arg (vargs, int));
570 break;
571 case 's': case 'S': { /* %s */
572 char *str = va_arg (vargs, char *);
573 if (str == (char*) 0) str = "(null)";
574 myvprintf_str(send, flags, width, str, format[i]=='S');
575 break;
576 }
577 default:
578 break;
579 }
580 }
581}
582
583
584/* A general replacement for printf(). Note that only low-level
585 debugging info should be sent via here. The official route is to
586 to use vg_message(). This interface is deprecated.
587*/
588static char myprintf_buf[100];
589static int n_myprintf_buf;
590
591static void add_to_myprintf_buf ( Char c )
592{
593 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
594 if (VG_(clo_logfile_fd) >= 0)
595 VG_(write)
596 (VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
597 n_myprintf_buf = 0;
598 myprintf_buf[n_myprintf_buf] = 0;
599 }
600 myprintf_buf[n_myprintf_buf++] = c;
601 myprintf_buf[n_myprintf_buf] = 0;
602}
603
604void VG_(printf) ( const char *format, ... )
605{
606 va_list vargs;
607 va_start(vargs,format);
608
609 n_myprintf_buf = 0;
610 myprintf_buf[n_myprintf_buf] = 0;
611 VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
612
613 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0)
614 VG_(write)
615 ( VG_(clo_logfile_fd), myprintf_buf, VG_(strlen)(myprintf_buf));
616
617 va_end(vargs);
618}
619
620
621/* A general replacement for sprintf(). */
622static Char* vg_sprintf_ptr;
623
624static void add_to_vg_sprintf_buf ( Char c )
625{
626 *vg_sprintf_ptr++ = c;
627}
628
629void VG_(sprintf) ( Char* buf, Char *format, ... )
630{
631 va_list vargs;
632 va_start(vargs,format);
633
634 vg_sprintf_ptr = buf;
635 VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
636 add_to_vg_sprintf_buf(0);
637
638 va_end(vargs);
639}
640
641
642/* ---------------------------------------------------------------------
643 Misc str* functions.
644 ------------------------------------------------------------------ */
645
646Bool VG_(isspace) ( Char c )
647{
648 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
649}
650
njn7cf0bd32002-06-08 13:36:03 +0000651Bool VG_(isdigit) ( Char c )
652{
653 return (c >= '0' && c <= '9');
654}
sewardjde4a1d02002-03-22 01:27:54 +0000655
656Int VG_(strlen) ( const Char* str )
657{
658 Int i = 0;
659 while (str[i] != 0) i++;
660 return i;
661}
662
663
664Long VG_(atoll) ( Char* str )
665{
666 Bool neg = False;
667 Long n = 0;
668 if (*str == '-') { str++; neg = True; };
669 while (*str >= '0' && *str <= '9') {
670 n = 10*n + (Long)(*str - '0');
671 str++;
672 }
673 if (neg) n = -n;
674 return n;
675}
676
677
njn25e49d8e72002-09-23 09:36:25 +0000678Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000679{
680 Bool neg = False;
681 Long n = 0;
682 if (*str == '-') { str++; neg = True; };
683 while (True) {
684 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000685 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000686 }
687 else
njn25e49d8e72002-09-23 09:36:25 +0000688 if (*str >= 'A' && *str <= 'F') {
689 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000690 }
691 else
njn25e49d8e72002-09-23 09:36:25 +0000692 if (*str >= 'a' && *str <= 'f') {
693 n = 16*n + (Long)((*str - 'a') + 10);
694 }
695 else {
696 break;
697 }
698 str++;
699 }
700 if (neg) n = -n;
701 return n;
702}
703
704Long VG_(atoll36) ( UInt base, Char* str )
705{
706 Bool neg = False;
707 Long n = 0;
708 vg_assert(base >= 2 && base <= 36);
709 if (*str == '-') { str++; neg = True; };
710 while (True) {
711 if (*str >= '0' && *str <=('9' - (10 - base))) {
712 n = base*n + (Long)(*str - '0');
713 }
714 else
715 if (base > 10 && *str >= 'A' && *str <= ('Z' - (36 - base))) {
716 n = base*n + (Long)((*str - 'A') + 10);
717 }
718 else
719 if (base > 10 && *str >= 'a' && *str <= ('z' - (36 - base))) {
720 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000721 }
722 else {
723 break;
724 }
725 str++;
726 }
727 if (neg) n = -n;
728 return n;
729}
730
731
sewardjde4a1d02002-03-22 01:27:54 +0000732Char* VG_(strcat) ( Char* dest, const Char* src )
733{
734 Char* dest_orig = dest;
735 while (*dest) dest++;
736 while (*src) *dest++ = *src++;
737 *dest = 0;
738 return dest_orig;
739}
740
741
742Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
743{
744 Char* dest_orig = dest;
745 while (*dest) dest++;
746 while (*src && n > 0) { *dest++ = *src++; n--; }
747 *dest = 0;
748 return dest_orig;
749}
750
751
752Char* VG_(strpbrk) ( const Char* s, const Char* accept )
753{
754 const Char* a;
755 while (*s) {
756 a = accept;
757 while (*a)
758 if (*a++ == *s)
759 return (Char *) s;
760 s++;
761 }
762 return NULL;
763}
764
765
766Char* VG_(strcpy) ( Char* dest, const Char* src )
767{
768 Char* dest_orig = dest;
769 while (*src) *dest++ = *src++;
770 *dest = 0;
771 return dest_orig;
772}
773
774
775/* Copy bytes, not overrunning the end of dest and always ensuring
776 zero termination. */
777void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
778{
779 Int i;
780 vg_assert(ndest > 0);
781 i = 0;
782 dest[i] = 0;
783 while (True) {
784 if (src[i] == 0) return;
785 if (i >= ndest-1) return;
786 dest[i] = src[i];
787 i++;
788 dest[i] = 0;
789 }
790}
791
792
njn25e49d8e72002-09-23 09:36:25 +0000793Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000794{
njn25e49d8e72002-09-23 09:36:25 +0000795 Int i = 0;
796 while (True) {
797 if (i >= ndest) return dest; /* reached limit */
798 dest[i] = src[i];
799 if (src[i++] == 0) {
800 /* reached NUL; pad rest with zeroes as required */
801 while (i < ndest) dest[i++] = 0;
802 return dest;
803 }
804 }
sewardjde4a1d02002-03-22 01:27:54 +0000805}
806
807
808Int VG_(strcmp) ( const Char* s1, const Char* s2 )
809{
810 while (True) {
811 if (*s1 == 0 && *s2 == 0) return 0;
812 if (*s1 == 0) return -1;
813 if (*s2 == 0) return 1;
814
815 if (*(UChar*)s1 < *(UChar*)s2) return -1;
816 if (*(UChar*)s1 > *(UChar*)s2) return 1;
817
818 s1++; s2++;
819 }
820}
821
822
823Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
824{
825 while (True) {
826 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
827 if (VG_(isspace)(*s1)) return -1;
828 if (VG_(isspace)(*s2)) return 1;
829
830 if (*(UChar*)s1 < *(UChar*)s2) return -1;
831 if (*(UChar*)s1 > *(UChar*)s2) return 1;
832
833 s1++; s2++;
834 }
835}
836
837
838Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
839{
840 Int n = 0;
841 while (True) {
842 if (n >= nmax) return 0;
843 if (*s1 == 0 && *s2 == 0) return 0;
844 if (*s1 == 0) return -1;
845 if (*s2 == 0) return 1;
846
847 if (*(UChar*)s1 < *(UChar*)s2) return -1;
848 if (*(UChar*)s1 > *(UChar*)s2) return 1;
849
850 s1++; s2++; n++;
851 }
852}
853
854
855Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
856{
857 Int n = 0;
858 while (True) {
859 if (n >= nmax) return 0;
860 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
861 if (VG_(isspace)(*s1)) return -1;
862 if (VG_(isspace)(*s2)) return 1;
863
864 if (*(UChar*)s1 < *(UChar*)s2) return -1;
865 if (*(UChar*)s1 > *(UChar*)s2) return 1;
866
867 s1++; s2++; n++;
868 }
869}
870
871
872Char* VG_(strstr) ( const Char* haystack, Char* needle )
873{
sewardj3984b852002-05-12 03:00:17 +0000874 Int n;
875 if (haystack == NULL)
876 return NULL;
877 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000878 while (True) {
879 if (haystack[0] == 0)
880 return NULL;
881 if (VG_(strncmp)(haystack, needle, n) == 0)
882 return (Char*)haystack;
883 haystack++;
884 }
885}
886
887
888Char* VG_(strchr) ( const Char* s, Char c )
889{
890 while (True) {
891 if (*s == c) return (Char*)s;
892 if (*s == 0) return NULL;
893 s++;
894 }
895}
896
897
898Char VG_(toupper) ( Char c )
899{
900 if (c >= 'a' && c <= 'z')
901 return c + ('A' - 'a');
902 else
903 return c;
904}
905
906
njn25e49d8e72002-09-23 09:36:25 +0000907/* Inline just for the wrapper VG_(strdup) below */
908__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +0000909{
njn25e49d8e72002-09-23 09:36:25 +0000910 Int i;
911 Int len = VG_(strlen)(s) + 1;
912 Char* res = VG_(arena_malloc) (aid, len);
913 for (i = 0; i < len; i++)
914 res[i] = s[i];
915 return res;
sewardjde4a1d02002-03-22 01:27:54 +0000916}
917
njn25e49d8e72002-09-23 09:36:25 +0000918/* Wrapper to avoid exposing skins to ArenaId's */
919Char* VG_(strdup) ( const Char* s )
920{
921 return VG_(arena_strdup) ( VG_AR_SKIN, s );
922}
sewardjde4a1d02002-03-22 01:27:54 +0000923
924/* ---------------------------------------------------------------------
925 A simple string matching routine, purloined from Hugs98.
926 `*' matches any sequence of zero or more characters
927 `?' matches any single character exactly
928 `\c' matches the character c only (ignoring special chars)
929 c matches the character c only
930 ------------------------------------------------------------------ */
931
932/* Keep track of recursion depth. */
933static Int recDepth;
934
njn4ba5a792002-09-30 10:23:54 +0000935static Bool string_match_wrk ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +0000936{
sewardjcad5c212002-05-16 23:16:13 +0000937 vg_assert(recDepth >= 0 && recDepth < 250);
sewardjde4a1d02002-03-22 01:27:54 +0000938 recDepth++;
939 for (;;) {
940 switch (*pat) {
941 case '\0' : return (*str=='\0');
942 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +0000943 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +0000944 recDepth--;
945 return True;
946 }
947 } while (*str++);
948 recDepth--;
949 return False;
950 case '?' : if (*str++=='\0') {
951 recDepth--;
952 return False;
953 }
954 pat++;
955 break;
956 case '\\' : if (*++pat == '\0') {
957 recDepth--;
958 return False; /* spurious trailing \ in pattern */
959 }
960 /* falls through to ... */
961 default : if (*pat++ != *str++) {
962 recDepth--;
963 return False;
964 }
965 break;
966 }
967 }
968}
969
njn4ba5a792002-09-30 10:23:54 +0000970Bool VG_(string_match) ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +0000971{
972 Bool b;
973 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +0000974 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +0000975 /*
976 VG_(printf)("%s %s %s\n",
977 b?"TRUE ":"FALSE", pat, str);
978 */
979 return b;
980}
981
982
983/* ---------------------------------------------------------------------
984 Assertery.
985 ------------------------------------------------------------------ */
986
njne427a662002-10-02 11:08:25 +0000987__attribute__ ((noreturn))
988static void report_and_quit ( Char* report )
989{
990 VG_(pp_sched_status)();
991 VG_(printf)("Please report this bug to: %s\n\n", report);
992 VG_(shutdown_logging)();
993 VG_(exit)(1);
994}
995
996__attribute__ ((noreturn))
997static void assert_fail ( Char* expr, Char* name, Char* report,
998 Char* file, Int line, Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +0000999{
sewardj018f7622002-05-15 21:13:39 +00001000 static Bool entered = False;
1001 if (entered)
1002 VG_(exit)(2);
1003 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001004 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001005 name, file, line, fn, expr );
1006 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001007}
1008
njne427a662002-10-02 11:08:25 +00001009void VG_(skin_assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001010{
njne427a662002-10-02 11:08:25 +00001011 assert_fail(expr, VG_(needs).name, VG_(needs).bug_reports_to,
1012 file, line, fn);
1013}
1014
1015void VG_(core_assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
1016{
1017 assert_fail(expr, "valgrind", VG_EMAIL_ADDR, file, line, fn);
1018}
1019
1020__attribute__ ((noreturn))
1021static void panic ( Char* name, Char* report, Char* str )
1022{
1023 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001024 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
njne427a662002-10-02 11:08:25 +00001025 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001026}
1027
njne427a662002-10-02 11:08:25 +00001028void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001029{
njne427a662002-10-02 11:08:25 +00001030 panic("valgrind", VG_EMAIL_ADDR, str);
njn25e49d8e72002-09-23 09:36:25 +00001031}
1032
njne427a662002-10-02 11:08:25 +00001033void VG_(skin_panic) ( Char* str )
1034{
1035 panic(VG_(needs).name, VG_(needs).bug_reports_to, str);
1036}
sewardjde4a1d02002-03-22 01:27:54 +00001037
1038/* ---------------------------------------------------------------------
1039 Primitive support for reading files.
1040 ------------------------------------------------------------------ */
1041
1042/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001043Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1044{
sewardjde4a1d02002-03-22 01:27:54 +00001045 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001046
njn25e49d8e72002-09-23 09:36:25 +00001047 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001048 /* This gets a segmentation fault if pathname isn't a valid file.
1049 I don't know why. It seems like the call to open is getting
1050 intercepted and messed with by glibc ... */
1051 /* fd = open( pathname, O_RDONLY ); */
1052 /* ... so we go direct to the horse's mouth, which seems to work
1053 ok: */
njn25e49d8e72002-09-23 09:36:25 +00001054 fd = vg_do_syscall3(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001055 /* VG_(printf)("result = %d\n", fd); */
1056 if (VG_(is_kerror)(fd)) {
1057 fd = -1;
1058 }
1059 return fd;
1060}
sewardjde4a1d02002-03-22 01:27:54 +00001061
1062void VG_(close) ( Int fd )
1063{
1064 vg_do_syscall1(__NR_close, fd);
1065}
1066
1067
1068Int VG_(read) ( Int fd, void* buf, Int count)
1069{
1070 Int res;
1071 /* res = read( fd, buf, count ); */
1072 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
1073 if (VG_(is_kerror)(res)) res = -1;
1074 return res;
1075}
1076
1077Int VG_(write) ( Int fd, void* buf, Int count)
1078{
1079 Int res;
1080 /* res = write( fd, buf, count ); */
1081 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
1082 if (VG_(is_kerror)(res)) res = -1;
1083 return res;
1084}
1085
sewardjb3586202002-05-09 17:38:13 +00001086Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1087{
1088 Int res;
1089 res = vg_do_syscall2(__NR_stat, (UInt)file_name, (UInt)buf);
1090 return
1091 VG_(is_kerror)(res) ? (-1) : 0;
1092}
1093
sewardjde4a1d02002-03-22 01:27:54 +00001094/* Misc functions looking for a proper home. */
1095
1096/* We do getenv without libc's help by snooping around in
njn25e49d8e72002-09-23 09:36:25 +00001097 VG_(client_envp) as determined at startup time. */
sewardjde4a1d02002-03-22 01:27:54 +00001098Char* VG_(getenv) ( Char* varname )
1099{
1100 Int i, n;
1101 n = VG_(strlen)(varname);
1102 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1103 Char* s = VG_(client_envp)[i];
1104 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1105 return & s[n+1];
1106 }
1107 }
1108 return NULL;
1109}
1110
1111/* You'd be amazed how many places need to know the current pid. */
1112Int VG_(getpid) ( void )
1113{
1114 Int res;
1115 /* res = getpid(); */
1116 res = vg_do_syscall0(__NR_getpid);
1117 return res;
1118}
1119
sewardje6a25242002-04-21 22:03:07 +00001120/* Return -1 if error, else 0. NOTE does not indicate return code of
1121 child! */
1122Int VG_(system) ( Char* cmd )
1123{
1124 Int pid, res;
1125 void* environ[1] = { NULL };
1126 if (cmd == NULL)
1127 return 1;
1128 pid = vg_do_syscall0(__NR_fork);
1129 if (VG_(is_kerror)(pid))
1130 return -1;
1131 if (pid == 0) {
1132 /* child */
1133 Char* argv[4];
1134 argv[0] = "/bin/sh";
1135 argv[1] = "-c";
1136 argv[2] = cmd;
1137 argv[3] = 0;
1138 (void)vg_do_syscall3(__NR_execve,
1139 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
1140 /* If we're still alive here, execve failed. */
1141 return -1;
1142 } else {
1143 /* parent */
1144 res = vg_do_syscall3(__NR_waitpid, pid, (UInt)NULL, 0);
1145 if (VG_(is_kerror)(res)) {
1146 return -1;
1147 } else {
1148 return 0;
1149 }
1150 }
1151}
1152
1153
sewardjde4a1d02002-03-22 01:27:54 +00001154/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001155 Support for a millisecond-granularity counter using RDTSC.
1156 ------------------------------------------------------------------ */
1157
1158static __inline__ ULong do_rdtsc_insn ( void )
1159{
1160 ULong x;
1161 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1162 return x;
1163}
1164
1165/* 0 = pre-calibration, 1 = calibration, 2 = running */
1166static Int rdtsc_calibration_state = 0;
1167static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1168
1169static struct vki_timeval rdtsc_cal_start_timeval;
1170static struct vki_timeval rdtsc_cal_end_timeval;
1171
1172static ULong rdtsc_cal_start_raw;
1173static ULong rdtsc_cal_end_raw;
1174
1175UInt VG_(read_millisecond_timer) ( void )
1176{
1177 ULong rdtsc_now;
1178 vg_assert(rdtsc_calibration_state == 2);
1179 rdtsc_now = do_rdtsc_insn();
1180 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1181 rdtsc_now -= rdtsc_cal_end_raw;
1182 rdtsc_now /= rdtsc_ticks_per_millisecond;
1183 return (UInt)rdtsc_now;
1184}
1185
1186
1187void VG_(start_rdtsc_calibration) ( void )
1188{
1189 Int res;
1190 vg_assert(rdtsc_calibration_state == 0);
1191 rdtsc_calibration_state = 1;
1192 rdtsc_cal_start_raw = do_rdtsc_insn();
1193 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1194 (UInt)NULL);
1195 vg_assert(!VG_(is_kerror)(res));
1196}
1197
1198void VG_(end_rdtsc_calibration) ( void )
1199{
1200 Int res, loops;
1201 ULong cpu_clock_MHZ;
1202 ULong cal_clock_ticks;
1203 ULong cal_wallclock_microseconds;
1204 ULong wallclock_start_microseconds;
1205 ULong wallclock_end_microseconds;
1206 struct vki_timespec req;
1207 struct vki_timespec rem;
1208
1209 vg_assert(rdtsc_calibration_state == 1);
1210 rdtsc_calibration_state = 2;
1211
1212 /* Try and delay for 20 milliseconds, so that we can at least have
1213 some minimum level of accuracy. */
1214 req.tv_sec = 0;
1215 req.tv_nsec = 20 * 1000 * 1000;
1216 loops = 0;
1217 while (True) {
1218 res = VG_(nanosleep)(&req, &rem);
1219 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1220 if (res == 0)
1221 break;
1222 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1223 break;
1224 req = rem;
1225 loops++;
1226 if (loops > 100)
njne427a662002-10-02 11:08:25 +00001227 VG_(core_panic)("calibration nanosleep loop failed?!");
sewardj5f07b662002-04-23 16:52:51 +00001228 }
1229
1230 /* Now read both timers, and do the Math. */
1231 rdtsc_cal_end_raw = do_rdtsc_insn();
1232 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1233 (UInt)NULL);
1234
1235 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1236 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1237
1238 wallclock_start_microseconds
1239 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1240 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1241 wallclock_end_microseconds
1242 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1243 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1244 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1245 cal_wallclock_microseconds
1246 = wallclock_end_microseconds - wallclock_start_microseconds;
1247
1248 /* Since we just nanoslept for 20 ms ... */
1249 vg_assert(cal_wallclock_microseconds >= 20000);
1250
1251 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1252 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1253 ticks-per-millisecond value. */
1254 if (0)
1255 VG_(printf)("%lld ticks in %lld microseconds\n",
1256 cal_clock_ticks, cal_wallclock_microseconds );
1257
1258 rdtsc_ticks_per_millisecond
1259 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1260 cpu_clock_MHZ
1261 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1262 if (VG_(clo_verbosity) >= 1)
1263 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1264 (UInt)cpu_clock_MHZ);
sewardj09c55fd2002-06-13 11:37:41 +00001265 if (cpu_clock_MHZ < 50 || cpu_clock_MHZ > 10000)
njne427a662002-10-02 11:08:25 +00001266 VG_(core_panic)("end_rdtsc_calibration: "
sewardj09c55fd2002-06-13 11:37:41 +00001267 "estimated CPU MHz outside range 50 .. 10000");
sewardj5f07b662002-04-23 16:52:51 +00001268 /* Paranoia about division by zero later. */
1269 vg_assert(rdtsc_ticks_per_millisecond != 0);
1270 if (0)
1271 VG_(printf)("ticks per millisecond %llu\n",
1272 rdtsc_ticks_per_millisecond);
1273}
1274
1275
1276
1277/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001278 Primitive support for bagging memory via mmap.
1279 ------------------------------------------------------------------ */
1280
sewardje9047952002-06-05 20:28:33 +00001281void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001282{
1283 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001284 void* p;
1285 p = VG_(mmap)( 0, nBytes,
1286 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1287 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001288 if (p != ((void*)(-1))) {
1289 tot_alloc += (UInt)nBytes;
1290 if (0)
sewardje9047952002-06-05 20:28:33 +00001291 VG_(printf)(
1292 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1293 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001294 return p;
1295 }
sewardj7c2020b2002-09-30 22:56:03 +00001296
njn25e49d8e72002-09-23 09:36:25 +00001297 VG_(printf)("\n");
1298 VG_(printf)("VG_(get_memory_from_mmap): request for %d bytes failed.\n",
sewardjde4a1d02002-03-22 01:27:54 +00001299 nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001300 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1301 tot_alloc);
1302 VG_(printf)("\n");
1303 VG_(printf)("This may mean that you have run out of swap space,\n");
1304 VG_(printf)("since running programs on valgrind increases their memory\n");
1305 VG_(printf)("usage at least 3 times. You might want to use 'top'\n");
1306 VG_(printf)("to determine whether you really have run out of swap.\n");
1307 VG_(printf)("If so, you may be able to work around it by adding a\n");
1308 VG_(printf)("temporary swap file -- this is easier than finding a\n");
1309 VG_(printf)("new swap partition. Go ask your sysadmin(s) [politely!]\n");
1310 VG_(printf)("\n");
1311 VG_(printf)("VG_(get_memory_from_mmap): out of memory! Fatal! Bye!\n");
1312 VG_(printf)("\n");
1313 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001314}
1315
njn25e49d8e72002-09-23 09:36:25 +00001316/* ---------------------------------------------------------------------
1317 Generally useful...
1318 ------------------------------------------------------------------ */
1319
1320Int VG_(log2) ( Int x )
1321{
1322 Int i;
1323 /* Any more than 32 and we overflow anyway... */
1324 for (i = 0; i < 32; i++) {
1325 if (1 << i == x) return i;
1326 }
1327 return -1;
1328}
1329
1330
sewardjde4a1d02002-03-22 01:27:54 +00001331
1332/*--------------------------------------------------------------------*/
1333/*--- end vg_mylibc.c ---*/
1334/*--------------------------------------------------------------------*/