blob: d828569887d791f68b8b643ccd1ca76fe59593e5 [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/*
njnc9539842002-10-02 13:26:35 +00009 This file is part of Valgrind, an extensible x86 protected-mode
10 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000011
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. */
sewardj78e3cd92002-10-22 04:45:48 +0000393#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
sewardjde4a1d02002-03-22 01:27:54 +0000394
395/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000396static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000397myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
398 Bool capitalise )
399{
400# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000401 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000402 Int i, extra;
403 Int len = VG_(strlen)(str);
404
405 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000406 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000407 for (i = 0; i < len; i++)
408 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000409 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000410 }
411
412 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000413 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000414 for (i = 0; i < width; i++)
415 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000416 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000417 }
418
419 extra = width - len;
420 if (flags & VG_MSG_LJUSTIFY) {
sewardj78e3cd92002-10-22 04:45:48 +0000421 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000422 for (i = 0; i < extra; i++)
423 send(' ');
424 }
sewardj78e3cd92002-10-22 04:45:48 +0000425 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000426 for (i = 0; i < len; i++)
427 send(MAYBE_TOUPPER(str[i]));
428 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000429 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000430 for (i = 0; i < extra; i++)
431 send(' ');
432 }
433
434# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000435
436 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000437}
438
439/* Write P into the buffer according to these args:
440 * If SIGN is true, p is a signed.
441 * BASE is the base.
442 * If WITH_ZERO is true, '0' must be added.
443 * WIDTH is the width of the field.
444 */
sewardj78e3cd92002-10-22 04:45:48 +0000445static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000446myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
447{
448 Char buf[40];
449 Int ind = 0;
450 Int i;
451 Bool neg = False;
452 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000453 UInt ret = 0;
454
sewardjde4a1d02002-03-22 01:27:54 +0000455 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000456 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000457
458 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
459 p = - (Long)p;
460 neg = True;
461 }
462
463 if (p == 0)
464 buf[ind++] = '0';
465 else {
466 while (p > 0) {
467 buf[ind++] = digits[p % base];
468 p /= base;
469 }
470 }
471
472 if (neg)
473 buf[ind++] = '-';
474
475 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
476 for(; ind < width; ind++) {
477 vg_assert(ind < 39);
478 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
479 }
480 }
481
482 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000483 ret += ind;
sewardjde4a1d02002-03-22 01:27:54 +0000484 for (i = ind -1; i >= 0; i--)
485 send(buf[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000486 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000487 for(; ind < width; ind++) {
488 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000489 send((flags & VG_MSG_ZJUSTIFY) ? '0': ' ');
sewardj78e3cd92002-10-22 04:45:48 +0000490 }
sewardjde4a1d02002-03-22 01:27:54 +0000491 }
sewardj78e3cd92002-10-22 04:45:48 +0000492 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000493}
494
495
496/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000497UInt
sewardjde4a1d02002-03-22 01:27:54 +0000498VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
499{
sewardj78e3cd92002-10-22 04:45:48 +0000500 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000501 int i;
502 int flags;
503 int width;
504 Bool is_long;
505
506 /* We assume that vargs has already been initialised by the
507 caller, using va_start, and that the caller will similarly
508 clean up with va_end.
509 */
510
511 for (i = 0; format[i] != 0; i++) {
512 if (format[i] != '%') {
513 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000514 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000515 continue;
516 }
517 i++;
518 /* A '%' has been found. Ignore a trailing %. */
519 if (format[i] == 0)
520 break;
521 if (format[i] == '%') {
522 /* `%%' is replaced by `%'. */
523 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000524 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000525 continue;
526 }
527 flags = 0;
528 is_long = False;
529 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000530 if (format[i] == '(') {
531 flags |= VG_MSG_PAREN;
532 i++;
533 }
sewardjde4a1d02002-03-22 01:27:54 +0000534 /* If '-' follows '%', justify on the left. */
535 if (format[i] == '-') {
536 flags |= VG_MSG_LJUSTIFY;
537 i++;
538 }
539 /* If '0' follows '%', pads will be inserted. */
540 if (format[i] == '0') {
541 flags |= VG_MSG_ZJUSTIFY;
542 i++;
543 }
544 /* Compute the field length. */
545 while (format[i] >= '0' && format[i] <= '9') {
546 width *= 10;
547 width += format[i++] - '0';
548 }
549 while (format[i] == 'l') {
550 i++;
551 is_long = True;
552 }
553
554 switch (format[i]) {
555 case 'd': /* %d */
556 flags |= VG_MSG_SIGNED;
557 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000558 ret += myvprintf_int64(send, flags, 10, width,
559 (ULong)(va_arg (vargs, Long)));
sewardjde4a1d02002-03-22 01:27:54 +0000560 else
sewardj78e3cd92002-10-22 04:45:48 +0000561 ret += myvprintf_int64(send, flags, 10, width,
562 (ULong)(va_arg (vargs, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000563 break;
564 case 'u': /* %u */
565 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000566 ret += myvprintf_int64(send, flags, 10, width,
567 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000568 else
sewardj78e3cd92002-10-22 04:45:48 +0000569 ret += myvprintf_int64(send, flags, 10, width,
570 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000571 break;
572 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000573 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000574 send('0');
575 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000576 ret += myvprintf_int64(send, flags, 16, width,
577 (ULong)((UInt)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000578 break;
579 case 'x': /* %x */
580 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000581 ret += myvprintf_int64(send, flags, 16, width,
582 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000583 else
sewardj78e3cd92002-10-22 04:45:48 +0000584 ret += myvprintf_int64(send, flags, 16, width,
585 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000586 break;
587 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000588 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000589 send(va_arg (vargs, int));
590 break;
591 case 's': case 'S': { /* %s */
592 char *str = va_arg (vargs, char *);
593 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000594 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000595 break;
sewardj78e3cd92002-10-22 04:45:48 +0000596 }
597 case 'y': { /* %y - print symbol */
598 Char buf[100];
599 Char *cp = buf;
600 Addr a = va_arg(vargs, Addr);
601
602 if (flags & VG_MSG_PAREN)
603 *cp++ = '(';
604 if (VG_(get_fnname)(a, cp, sizeof(buf)-2)) {
605 if (flags & VG_MSG_PAREN) {
606 cp += VG_(strlen)(cp);
607 *cp++ = ')';
608 *cp = '\0';
609 }
610 ret += myvprintf_str(send, flags, width, buf, 0);
611 }
612
613 break;
614 }
sewardjde4a1d02002-03-22 01:27:54 +0000615 default:
616 break;
617 }
618 }
sewardj78e3cd92002-10-22 04:45:48 +0000619 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000620}
621
622
623/* A general replacement for printf(). Note that only low-level
624 debugging info should be sent via here. The official route is to
625 to use vg_message(). This interface is deprecated.
626*/
627static char myprintf_buf[100];
628static int n_myprintf_buf;
629
630static void add_to_myprintf_buf ( Char c )
631{
632 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
sewardj73cf3bc2002-11-03 03:20:15 +0000633 if (VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000634 VG_(send_bytes_to_logging_sink)(
635 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000636 }
sewardjde4a1d02002-03-22 01:27:54 +0000637 n_myprintf_buf = 0;
638 myprintf_buf[n_myprintf_buf] = 0;
639 }
640 myprintf_buf[n_myprintf_buf++] = c;
641 myprintf_buf[n_myprintf_buf] = 0;
642}
643
sewardj78e3cd92002-10-22 04:45:48 +0000644UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000645{
sewardj78e3cd92002-10-22 04:45:48 +0000646 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000647 va_list vargs;
648 va_start(vargs,format);
649
650 n_myprintf_buf = 0;
651 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000652 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000653
sewardj73cf3bc2002-11-03 03:20:15 +0000654 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000655 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000656 }
sewardjde4a1d02002-03-22 01:27:54 +0000657
658 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000659
660 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000661}
662
663
664/* A general replacement for sprintf(). */
665static Char* vg_sprintf_ptr;
666
667static void add_to_vg_sprintf_buf ( Char c )
668{
669 *vg_sprintf_ptr++ = c;
670}
671
sewardj78e3cd92002-10-22 04:45:48 +0000672UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000673{
sewardj78e3cd92002-10-22 04:45:48 +0000674 UInt ret;
675
sewardjde4a1d02002-03-22 01:27:54 +0000676 va_list vargs;
677 va_start(vargs,format);
678
679 vg_sprintf_ptr = buf;
sewardj78e3cd92002-10-22 04:45:48 +0000680 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000681 add_to_vg_sprintf_buf(0);
682
683 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000684
685 vg_assert(VG_(strlen)(buf) == ret);
686 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000687}
688
689
690/* ---------------------------------------------------------------------
691 Misc str* functions.
692 ------------------------------------------------------------------ */
693
694Bool VG_(isspace) ( Char c )
695{
696 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
697}
698
njn7cf0bd32002-06-08 13:36:03 +0000699Bool VG_(isdigit) ( Char c )
700{
701 return (c >= '0' && c <= '9');
702}
sewardjde4a1d02002-03-22 01:27:54 +0000703
704Int VG_(strlen) ( const Char* str )
705{
706 Int i = 0;
707 while (str[i] != 0) i++;
708 return i;
709}
710
711
712Long VG_(atoll) ( Char* str )
713{
714 Bool neg = False;
715 Long n = 0;
716 if (*str == '-') { str++; neg = True; };
717 while (*str >= '0' && *str <= '9') {
718 n = 10*n + (Long)(*str - '0');
719 str++;
720 }
721 if (neg) n = -n;
722 return n;
723}
724
725
njn25e49d8e72002-09-23 09:36:25 +0000726Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000727{
728 Bool neg = False;
729 Long n = 0;
730 if (*str == '-') { str++; neg = True; };
731 while (True) {
732 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000733 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000734 }
735 else
njn25e49d8e72002-09-23 09:36:25 +0000736 if (*str >= 'A' && *str <= 'F') {
737 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000738 }
739 else
njn25e49d8e72002-09-23 09:36:25 +0000740 if (*str >= 'a' && *str <= 'f') {
741 n = 16*n + (Long)((*str - 'a') + 10);
742 }
743 else {
744 break;
745 }
746 str++;
747 }
748 if (neg) n = -n;
749 return n;
750}
751
752Long VG_(atoll36) ( UInt base, Char* str )
753{
754 Bool neg = False;
755 Long n = 0;
756 vg_assert(base >= 2 && base <= 36);
757 if (*str == '-') { str++; neg = True; };
758 while (True) {
759 if (*str >= '0' && *str <=('9' - (10 - base))) {
760 n = base*n + (Long)(*str - '0');
761 }
762 else
763 if (base > 10 && *str >= 'A' && *str <= ('Z' - (36 - base))) {
764 n = base*n + (Long)((*str - 'A') + 10);
765 }
766 else
767 if (base > 10 && *str >= 'a' && *str <= ('z' - (36 - base))) {
768 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000769 }
770 else {
771 break;
772 }
773 str++;
774 }
775 if (neg) n = -n;
776 return n;
777}
778
779
sewardjde4a1d02002-03-22 01:27:54 +0000780Char* VG_(strcat) ( Char* dest, const Char* src )
781{
782 Char* dest_orig = dest;
783 while (*dest) dest++;
784 while (*src) *dest++ = *src++;
785 *dest = 0;
786 return dest_orig;
787}
788
789
790Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
791{
792 Char* dest_orig = dest;
793 while (*dest) dest++;
794 while (*src && n > 0) { *dest++ = *src++; n--; }
795 *dest = 0;
796 return dest_orig;
797}
798
799
800Char* VG_(strpbrk) ( const Char* s, const Char* accept )
801{
802 const Char* a;
803 while (*s) {
804 a = accept;
805 while (*a)
806 if (*a++ == *s)
807 return (Char *) s;
808 s++;
809 }
810 return NULL;
811}
812
813
814Char* VG_(strcpy) ( Char* dest, const Char* src )
815{
816 Char* dest_orig = dest;
817 while (*src) *dest++ = *src++;
818 *dest = 0;
819 return dest_orig;
820}
821
822
823/* Copy bytes, not overrunning the end of dest and always ensuring
824 zero termination. */
825void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
826{
827 Int i;
828 vg_assert(ndest > 0);
829 i = 0;
830 dest[i] = 0;
831 while (True) {
832 if (src[i] == 0) return;
833 if (i >= ndest-1) return;
834 dest[i] = src[i];
835 i++;
836 dest[i] = 0;
837 }
838}
839
840
njn25e49d8e72002-09-23 09:36:25 +0000841Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000842{
njn25e49d8e72002-09-23 09:36:25 +0000843 Int i = 0;
844 while (True) {
845 if (i >= ndest) return dest; /* reached limit */
846 dest[i] = src[i];
847 if (src[i++] == 0) {
848 /* reached NUL; pad rest with zeroes as required */
849 while (i < ndest) dest[i++] = 0;
850 return dest;
851 }
852 }
sewardjde4a1d02002-03-22 01:27:54 +0000853}
854
855
856Int VG_(strcmp) ( const Char* s1, const Char* s2 )
857{
858 while (True) {
859 if (*s1 == 0 && *s2 == 0) return 0;
860 if (*s1 == 0) return -1;
861 if (*s2 == 0) return 1;
862
863 if (*(UChar*)s1 < *(UChar*)s2) return -1;
864 if (*(UChar*)s1 > *(UChar*)s2) return 1;
865
866 s1++; s2++;
867 }
868}
869
870
871Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
872{
873 while (True) {
874 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
875 if (VG_(isspace)(*s1)) return -1;
876 if (VG_(isspace)(*s2)) return 1;
877
878 if (*(UChar*)s1 < *(UChar*)s2) return -1;
879 if (*(UChar*)s1 > *(UChar*)s2) return 1;
880
881 s1++; s2++;
882 }
883}
884
885
886Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
887{
888 Int n = 0;
889 while (True) {
890 if (n >= nmax) return 0;
891 if (*s1 == 0 && *s2 == 0) return 0;
892 if (*s1 == 0) return -1;
893 if (*s2 == 0) return 1;
894
895 if (*(UChar*)s1 < *(UChar*)s2) return -1;
896 if (*(UChar*)s1 > *(UChar*)s2) return 1;
897
898 s1++; s2++; n++;
899 }
900}
901
902
903Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
904{
905 Int n = 0;
906 while (True) {
907 if (n >= nmax) return 0;
908 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
909 if (VG_(isspace)(*s1)) return -1;
910 if (VG_(isspace)(*s2)) return 1;
911
912 if (*(UChar*)s1 < *(UChar*)s2) return -1;
913 if (*(UChar*)s1 > *(UChar*)s2) return 1;
914
915 s1++; s2++; n++;
916 }
917}
918
919
920Char* VG_(strstr) ( const Char* haystack, Char* needle )
921{
sewardj3984b852002-05-12 03:00:17 +0000922 Int n;
923 if (haystack == NULL)
924 return NULL;
925 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000926 while (True) {
927 if (haystack[0] == 0)
928 return NULL;
929 if (VG_(strncmp)(haystack, needle, n) == 0)
930 return (Char*)haystack;
931 haystack++;
932 }
933}
934
935
936Char* VG_(strchr) ( const Char* s, Char c )
937{
938 while (True) {
939 if (*s == c) return (Char*)s;
940 if (*s == 0) return NULL;
941 s++;
942 }
943}
944
945
sewardj7ab2aca2002-10-20 19:40:32 +0000946void* VG_(memcpy) ( void *dest, const void *src, Int sz )
947{
948 const Char *s = (const Char *)src;
949 Char *d = (Char *)dest;
950 vg_assert(sz >= 0);
951
952 while (sz--)
953 *d++ = *s++;
954
955 return dest;
956}
957
958
959void* VG_(memset) ( void *dest, Int c, Int sz )
960{
961 Char *d = (Char *)dest;
962 vg_assert(sz >= 0);
963
964 while (sz--)
965 *d++ = c;
966
967 return dest;
968}
969
970
sewardjde4a1d02002-03-22 01:27:54 +0000971Char VG_(toupper) ( Char c )
972{
973 if (c >= 'a' && c <= 'z')
974 return c + ('A' - 'a');
975 else
976 return c;
977}
978
979
njn25e49d8e72002-09-23 09:36:25 +0000980/* Inline just for the wrapper VG_(strdup) below */
981__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +0000982{
njn25e49d8e72002-09-23 09:36:25 +0000983 Int i;
984 Int len = VG_(strlen)(s) + 1;
985 Char* res = VG_(arena_malloc) (aid, len);
986 for (i = 0; i < len; i++)
987 res[i] = s[i];
988 return res;
sewardjde4a1d02002-03-22 01:27:54 +0000989}
990
njn25e49d8e72002-09-23 09:36:25 +0000991/* Wrapper to avoid exposing skins to ArenaId's */
992Char* VG_(strdup) ( const Char* s )
993{
994 return VG_(arena_strdup) ( VG_AR_SKIN, s );
995}
sewardjde4a1d02002-03-22 01:27:54 +0000996
997/* ---------------------------------------------------------------------
998 A simple string matching routine, purloined from Hugs98.
999 `*' matches any sequence of zero or more characters
1000 `?' matches any single character exactly
1001 `\c' matches the character c only (ignoring special chars)
1002 c matches the character c only
1003 ------------------------------------------------------------------ */
1004
1005/* Keep track of recursion depth. */
1006static Int recDepth;
1007
njn4ba5a792002-09-30 10:23:54 +00001008static Bool string_match_wrk ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001009{
sewardjcad5c212002-05-16 23:16:13 +00001010 vg_assert(recDepth >= 0 && recDepth < 250);
sewardjde4a1d02002-03-22 01:27:54 +00001011 recDepth++;
1012 for (;;) {
1013 switch (*pat) {
1014 case '\0' : return (*str=='\0');
1015 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001016 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001017 recDepth--;
1018 return True;
1019 }
1020 } while (*str++);
1021 recDepth--;
1022 return False;
1023 case '?' : if (*str++=='\0') {
1024 recDepth--;
1025 return False;
1026 }
1027 pat++;
1028 break;
1029 case '\\' : if (*++pat == '\0') {
1030 recDepth--;
1031 return False; /* spurious trailing \ in pattern */
1032 }
1033 /* falls through to ... */
1034 default : if (*pat++ != *str++) {
1035 recDepth--;
1036 return False;
1037 }
1038 break;
1039 }
1040 }
1041}
1042
njn4ba5a792002-09-30 10:23:54 +00001043Bool VG_(string_match) ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001044{
1045 Bool b;
1046 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001047 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001048 /*
1049 VG_(printf)("%s %s %s\n",
1050 b?"TRUE ":"FALSE", pat, str);
1051 */
1052 return b;
1053}
1054
1055
1056/* ---------------------------------------------------------------------
1057 Assertery.
1058 ------------------------------------------------------------------ */
1059
njne427a662002-10-02 11:08:25 +00001060__attribute__ ((noreturn))
1061static void report_and_quit ( Char* report )
1062{
1063 VG_(pp_sched_status)();
1064 VG_(printf)("Please report this bug to: %s\n\n", report);
1065 VG_(shutdown_logging)();
1066 VG_(exit)(1);
1067}
1068
1069__attribute__ ((noreturn))
1070static void assert_fail ( Char* expr, Char* name, Char* report,
1071 Char* file, Int line, Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001072{
sewardj018f7622002-05-15 21:13:39 +00001073 static Bool entered = False;
1074 if (entered)
1075 VG_(exit)(2);
1076 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001077 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001078 name, file, line, fn, expr );
1079 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001080}
1081
njne427a662002-10-02 11:08:25 +00001082void VG_(skin_assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001083{
njnd04b7c62002-10-03 14:05:52 +00001084 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001085 file, line, fn);
1086}
1087
1088void VG_(core_assert_fail) ( Char* expr, Char* file, Int line, Char* fn )
1089{
1090 assert_fail(expr, "valgrind", VG_EMAIL_ADDR, file, line, fn);
1091}
1092
1093__attribute__ ((noreturn))
1094static void panic ( Char* name, Char* report, Char* str )
1095{
1096 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001097 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
njne427a662002-10-02 11:08:25 +00001098 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001099}
1100
njne427a662002-10-02 11:08:25 +00001101void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001102{
njne427a662002-10-02 11:08:25 +00001103 panic("valgrind", VG_EMAIL_ADDR, str);
njn25e49d8e72002-09-23 09:36:25 +00001104}
1105
njne427a662002-10-02 11:08:25 +00001106void VG_(skin_panic) ( Char* str )
1107{
njnd04b7c62002-10-03 14:05:52 +00001108 panic(VG_(details).name, VG_(details).bug_reports_to, str);
njne427a662002-10-02 11:08:25 +00001109}
sewardjde4a1d02002-03-22 01:27:54 +00001110
1111/* ---------------------------------------------------------------------
1112 Primitive support for reading files.
1113 ------------------------------------------------------------------ */
1114
1115/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001116Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1117{
sewardjde4a1d02002-03-22 01:27:54 +00001118 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001119
njn25e49d8e72002-09-23 09:36:25 +00001120 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001121 /* This gets a segmentation fault if pathname isn't a valid file.
1122 I don't know why. It seems like the call to open is getting
1123 intercepted and messed with by glibc ... */
1124 /* fd = open( pathname, O_RDONLY ); */
1125 /* ... so we go direct to the horse's mouth, which seems to work
1126 ok: */
njn25e49d8e72002-09-23 09:36:25 +00001127 fd = vg_do_syscall3(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001128 /* VG_(printf)("result = %d\n", fd); */
1129 if (VG_(is_kerror)(fd)) {
1130 fd = -1;
1131 }
1132 return fd;
1133}
sewardjde4a1d02002-03-22 01:27:54 +00001134
1135void VG_(close) ( Int fd )
1136{
1137 vg_do_syscall1(__NR_close, fd);
1138}
1139
1140
1141Int VG_(read) ( Int fd, void* buf, Int count)
1142{
1143 Int res;
1144 /* res = read( fd, buf, count ); */
1145 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
1146 if (VG_(is_kerror)(res)) res = -1;
1147 return res;
1148}
1149
1150Int VG_(write) ( Int fd, void* buf, Int count)
1151{
1152 Int res;
1153 /* res = write( fd, buf, count ); */
1154 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
1155 if (VG_(is_kerror)(res)) res = -1;
1156 return res;
1157}
1158
sewardjb3586202002-05-09 17:38:13 +00001159Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1160{
1161 Int res;
1162 res = vg_do_syscall2(__NR_stat, (UInt)file_name, (UInt)buf);
njn41557122002-10-14 09:25:37 +00001163 return VG_(is_kerror)(res) ? (-1) : 0;
1164}
1165
1166Int VG_(rename) ( Char* old_name, Char* new_name )
1167{
1168 Int res;
1169 res = vg_do_syscall2(__NR_rename, (UInt)old_name, (UInt)new_name);
1170 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001171}
1172
njn4aca2d22002-10-04 10:29:38 +00001173Int VG_(unlink) ( Char* file_name )
1174{
1175 Int res;
1176 res = vg_do_syscall1(__NR_unlink, (UInt)file_name);
njn41557122002-10-14 09:25:37 +00001177 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001178}
1179
sewardjde4a1d02002-03-22 01:27:54 +00001180/* Misc functions looking for a proper home. */
1181
1182/* We do getenv without libc's help by snooping around in
njn25e49d8e72002-09-23 09:36:25 +00001183 VG_(client_envp) as determined at startup time. */
sewardjde4a1d02002-03-22 01:27:54 +00001184Char* VG_(getenv) ( Char* varname )
1185{
1186 Int i, n;
1187 n = VG_(strlen)(varname);
1188 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1189 Char* s = VG_(client_envp)[i];
1190 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1191 return & s[n+1];
1192 }
1193 }
1194 return NULL;
1195}
1196
sewardj4cf05692002-10-27 20:28:29 +00001197
sewardjde4a1d02002-03-22 01:27:54 +00001198/* You'd be amazed how many places need to know the current pid. */
1199Int VG_(getpid) ( void )
1200{
1201 Int res;
1202 /* res = getpid(); */
1203 res = vg_do_syscall0(__NR_getpid);
1204 return res;
1205}
1206
sewardj4cf05692002-10-27 20:28:29 +00001207Int VG_(getppid) ( void )
1208{
1209 Int res;
1210 res = vg_do_syscall0(__NR_getppid);
1211 return res;
1212}
1213
1214
sewardje6a25242002-04-21 22:03:07 +00001215/* Return -1 if error, else 0. NOTE does not indicate return code of
1216 child! */
1217Int VG_(system) ( Char* cmd )
1218{
1219 Int pid, res;
1220 void* environ[1] = { NULL };
1221 if (cmd == NULL)
1222 return 1;
1223 pid = vg_do_syscall0(__NR_fork);
1224 if (VG_(is_kerror)(pid))
1225 return -1;
1226 if (pid == 0) {
1227 /* child */
1228 Char* argv[4];
1229 argv[0] = "/bin/sh";
1230 argv[1] = "-c";
1231 argv[2] = cmd;
1232 argv[3] = 0;
1233 (void)vg_do_syscall3(__NR_execve,
1234 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
1235 /* If we're still alive here, execve failed. */
1236 return -1;
1237 } else {
1238 /* parent */
1239 res = vg_do_syscall3(__NR_waitpid, pid, (UInt)NULL, 0);
1240 if (VG_(is_kerror)(res)) {
1241 return -1;
1242 } else {
1243 return 0;
1244 }
1245 }
1246}
1247
1248
sewardjde4a1d02002-03-22 01:27:54 +00001249/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001250 Support for a millisecond-granularity counter using RDTSC.
1251 ------------------------------------------------------------------ */
1252
1253static __inline__ ULong do_rdtsc_insn ( void )
1254{
1255 ULong x;
1256 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1257 return x;
1258}
1259
1260/* 0 = pre-calibration, 1 = calibration, 2 = running */
1261static Int rdtsc_calibration_state = 0;
1262static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1263
1264static struct vki_timeval rdtsc_cal_start_timeval;
1265static struct vki_timeval rdtsc_cal_end_timeval;
1266
1267static ULong rdtsc_cal_start_raw;
1268static ULong rdtsc_cal_end_raw;
1269
1270UInt VG_(read_millisecond_timer) ( void )
1271{
1272 ULong rdtsc_now;
1273 vg_assert(rdtsc_calibration_state == 2);
1274 rdtsc_now = do_rdtsc_insn();
1275 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1276 rdtsc_now -= rdtsc_cal_end_raw;
1277 rdtsc_now /= rdtsc_ticks_per_millisecond;
1278 return (UInt)rdtsc_now;
1279}
1280
1281
1282void VG_(start_rdtsc_calibration) ( void )
1283{
1284 Int res;
1285 vg_assert(rdtsc_calibration_state == 0);
1286 rdtsc_calibration_state = 1;
1287 rdtsc_cal_start_raw = do_rdtsc_insn();
1288 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1289 (UInt)NULL);
1290 vg_assert(!VG_(is_kerror)(res));
1291}
1292
1293void VG_(end_rdtsc_calibration) ( void )
1294{
1295 Int res, loops;
1296 ULong cpu_clock_MHZ;
1297 ULong cal_clock_ticks;
1298 ULong cal_wallclock_microseconds;
1299 ULong wallclock_start_microseconds;
1300 ULong wallclock_end_microseconds;
1301 struct vki_timespec req;
1302 struct vki_timespec rem;
1303
1304 vg_assert(rdtsc_calibration_state == 1);
1305 rdtsc_calibration_state = 2;
1306
1307 /* Try and delay for 20 milliseconds, so that we can at least have
1308 some minimum level of accuracy. */
1309 req.tv_sec = 0;
1310 req.tv_nsec = 20 * 1000 * 1000;
1311 loops = 0;
1312 while (True) {
1313 res = VG_(nanosleep)(&req, &rem);
1314 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1315 if (res == 0)
1316 break;
1317 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1318 break;
1319 req = rem;
1320 loops++;
1321 if (loops > 100)
njne427a662002-10-02 11:08:25 +00001322 VG_(core_panic)("calibration nanosleep loop failed?!");
sewardj5f07b662002-04-23 16:52:51 +00001323 }
1324
1325 /* Now read both timers, and do the Math. */
1326 rdtsc_cal_end_raw = do_rdtsc_insn();
1327 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1328 (UInt)NULL);
1329
1330 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1331 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1332
1333 wallclock_start_microseconds
1334 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1335 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1336 wallclock_end_microseconds
1337 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1338 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1339 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1340 cal_wallclock_microseconds
1341 = wallclock_end_microseconds - wallclock_start_microseconds;
1342
1343 /* Since we just nanoslept for 20 ms ... */
1344 vg_assert(cal_wallclock_microseconds >= 20000);
1345
1346 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1347 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1348 ticks-per-millisecond value. */
1349 if (0)
1350 VG_(printf)("%lld ticks in %lld microseconds\n",
1351 cal_clock_ticks, cal_wallclock_microseconds );
1352
1353 rdtsc_ticks_per_millisecond
1354 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1355 cpu_clock_MHZ
1356 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1357 if (VG_(clo_verbosity) >= 1)
1358 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1359 (UInt)cpu_clock_MHZ);
sewardj09c55fd2002-06-13 11:37:41 +00001360 if (cpu_clock_MHZ < 50 || cpu_clock_MHZ > 10000)
njne427a662002-10-02 11:08:25 +00001361 VG_(core_panic)("end_rdtsc_calibration: "
sewardj09c55fd2002-06-13 11:37:41 +00001362 "estimated CPU MHz outside range 50 .. 10000");
sewardj5f07b662002-04-23 16:52:51 +00001363 /* Paranoia about division by zero later. */
1364 vg_assert(rdtsc_ticks_per_millisecond != 0);
1365 if (0)
1366 VG_(printf)("ticks per millisecond %llu\n",
1367 rdtsc_ticks_per_millisecond);
1368}
1369
1370
1371
1372/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001373 Primitive support for bagging memory via mmap.
1374 ------------------------------------------------------------------ */
1375
sewardje9047952002-06-05 20:28:33 +00001376void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001377{
1378 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001379 void* p;
1380 p = VG_(mmap)( 0, nBytes,
1381 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1382 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001383 if (p != ((void*)(-1))) {
1384 tot_alloc += (UInt)nBytes;
1385 if (0)
sewardje9047952002-06-05 20:28:33 +00001386 VG_(printf)(
1387 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1388 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001389 return p;
1390 }
sewardj7c2020b2002-09-30 22:56:03 +00001391
njn25e49d8e72002-09-23 09:36:25 +00001392 VG_(printf)("\n");
1393 VG_(printf)("VG_(get_memory_from_mmap): request for %d bytes failed.\n",
sewardjde4a1d02002-03-22 01:27:54 +00001394 nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001395 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1396 tot_alloc);
1397 VG_(printf)("\n");
1398 VG_(printf)("This may mean that you have run out of swap space,\n");
1399 VG_(printf)("since running programs on valgrind increases their memory\n");
1400 VG_(printf)("usage at least 3 times. You might want to use 'top'\n");
1401 VG_(printf)("to determine whether you really have run out of swap.\n");
1402 VG_(printf)("If so, you may be able to work around it by adding a\n");
1403 VG_(printf)("temporary swap file -- this is easier than finding a\n");
1404 VG_(printf)("new swap partition. Go ask your sysadmin(s) [politely!]\n");
1405 VG_(printf)("\n");
1406 VG_(printf)("VG_(get_memory_from_mmap): out of memory! Fatal! Bye!\n");
1407 VG_(printf)("\n");
1408 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001409}
1410
njn25e49d8e72002-09-23 09:36:25 +00001411/* ---------------------------------------------------------------------
1412 Generally useful...
1413 ------------------------------------------------------------------ */
1414
1415Int VG_(log2) ( Int x )
1416{
1417 Int i;
1418 /* Any more than 32 and we overflow anyway... */
1419 for (i = 0; i < 32; i++) {
1420 if (1 << i == x) return i;
1421 }
1422 return -1;
1423}
1424
1425
sewardj73cf3bc2002-11-03 03:20:15 +00001426/* ---------------------------------------------------------------------
1427 Gruesome hackery for connecting to a logging server over the network.
1428 This is all very Linux-kernel specific.
1429 ------------------------------------------------------------------ */
1430
1431/* Various needed constants from the kernel iface (2.4),
1432 /usr/src/linux-2.4.9-31 */
1433
1434/* kernel, ./include/linux/net.h */
1435#define SYS_SOCKET 1 /* sys_socket(2) */
1436#define SYS_CONNECT 3 /* sys_connect(2) */
1437#define SYS_SEND 9 /* sys_send(2) */
1438
1439typedef UInt __u32;
1440
1441/* Internet address. */
1442struct vki_in_addr {
1443 __u32 s_addr;
1444};
1445
1446/* kernel, include/linux/socket.h */
1447typedef unsigned short vki_sa_family_t;
1448#define AF_INET 2 /* Internet IP Protocol */
sewardj570f8902002-11-03 11:44:36 +00001449#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
sewardj73cf3bc2002-11-03 03:20:15 +00001450
1451/* kernel, ./include/asm-i386/socket.h */
1452#define SOCK_STREAM 1 /* stream (connection) socket */
1453
1454/* kernel, /usr/src/linux-2.4.9-31/linux/include/in.h */
1455/* Structure describing an Internet (IP) socket address. */
1456#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
1457struct vki_sockaddr_in {
1458 vki_sa_family_t sin_family; /* Address family */
1459 unsigned short int sin_port; /* Port number */
1460 struct vki_in_addr sin_addr; /* Internet address */
1461
1462 /* Pad to size of `struct sockaddr'. */
1463 unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
1464 sizeof(unsigned short int) -
1465 sizeof(struct vki_in_addr)];
1466};
1467
1468
1469static
1470Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1471
1472static
1473Int my_socket ( Int domain, Int type, Int protocol );
1474
1475static
1476Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1477 Int addrlen );
1478
1479static
1480UInt my_htonl ( UInt x )
1481{
1482 return
1483 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1484 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1485}
1486
1487static
1488UShort my_htons ( UShort x )
1489{
1490 return
1491 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1492}
1493
1494
1495/* The main function.
1496
1497 Supplied string contains either an ip address "192.168.0.1" or
1498 an ip address and port pair, "192.168.0.1:1500". Parse these,
1499 and return:
1500 -1 if there is a parse error
1501 -2 if no parse error, but specified host:port cannot be opened
1502 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001503 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001504*/
1505Int VG_(connect_via_socket)( UChar* str )
1506{
1507 Int sd, res;
1508 struct vki_sockaddr_in servAddr;
1509 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001510 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001511 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1512 if (!ok)
1513 return -1;
1514
1515 if (0)
1516 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1517 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1518 (ip >> 8) & 0xFF, ip & 0xFF,
1519 (UInt)port );
1520
1521 servAddr.sin_family = AF_INET;
1522 servAddr.sin_addr.s_addr = my_htonl(ip);
1523 servAddr.sin_port = my_htons(port);
1524
1525 /* create socket */
1526 sd = my_socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1527 if (sd < 0) {
1528 /* this shouldn't happen ... nevertheless */
1529 return -2;
1530 }
1531
1532 /* connect to server */
1533 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1534 sizeof(servAddr));
1535 if (res < 0) {
1536 /* connection failed */
1537 return -2;
1538 }
1539
1540 return sd;
1541}
1542
1543
1544/* Let d = one or more digits. Accept either:
1545 d.d.d.d or d.d.d.d:d
1546*/
1547Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1548{
1549# define GET_CH ((*str) ? (*str++) : 0)
1550 UInt ipa, i, j, c, any;
1551 ipa = 0;
1552 for (i = 0; i < 4; i++) {
1553 j = 0;
1554 any = 0;
1555 while (1) {
1556 c = GET_CH;
1557 if (c < '0' || c > '9') break;
1558 j = 10 * j + (int)(c - '0');
1559 any = 1;
1560 }
1561 if (any == 0 || j > 255) goto syntaxerr;
1562 ipa = (ipa << 8) + j;
1563 if (i <= 2 && c != '.') goto syntaxerr;
1564 }
1565 if (c == 0 || c == ':')
1566 *ip_addr = ipa;
1567 if (c == 0) goto ok;
1568 if (c != ':') goto syntaxerr;
1569 j = 0;
1570 any = 0;
1571 while (1) {
1572 c = GET_CH;
1573 if (c < '0' || c > '9') break;
1574 j = j * 10 + (int)(c - '0');
1575 any = 1;
1576 if (j > 65535) goto syntaxerr;
1577 }
1578 if (any == 0 || c != 0) goto syntaxerr;
1579 *port = (UShort)j;
1580 ok:
1581 return 1;
1582 syntaxerr:
1583 return 0;
1584# undef GET_CH
1585}
1586
1587
1588static
1589Int my_socket ( Int domain, Int type, Int protocol )
1590{
1591 Int res;
1592 UInt args[3];
1593 args[0] = domain;
1594 args[1] = type;
1595 args[2] = protocol;
1596 res = vg_do_syscall2(__NR_socketcall, SYS_SOCKET, (UInt)&args);
1597 if (VG_(is_kerror)(res))
1598 res = -1;
1599 return res;
1600}
1601
1602static
1603Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1604 Int addrlen )
1605{
1606 Int res;
1607 UInt args[3];
1608 args[0] = sockfd;
1609 args[1] = (UInt)serv_addr;
1610 args[2] = addrlen;
1611 res = vg_do_syscall2(__NR_socketcall, SYS_CONNECT, (UInt)&args);
1612 if (VG_(is_kerror)(res))
1613 res = -1;
1614 return res;
1615}
1616
1617Int VG_(write_socket)( Int sd, void *msg, Int count )
1618{
1619 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001620
1621 /* Requests not to send SIGPIPE on errors on stream oriented
1622 sockets when the other end breaks the connection. The EPIPE
1623 error is still returned. */
1624 Int flags = MSG_NOSIGNAL;
1625
sewardj73cf3bc2002-11-03 03:20:15 +00001626 Int res;
1627 UInt args[4];
1628 args[0] = sd;
1629 args[1] = (UInt)msg;
1630 args[2] = count;
1631 args[3] = flags;
1632 res = vg_do_syscall2(__NR_socketcall, SYS_SEND, (UInt)&args);
1633 if (VG_(is_kerror)(res))
1634 res = -1;
1635 return res;
1636}
1637
sewardjde4a1d02002-03-22 01:27:54 +00001638
1639/*--------------------------------------------------------------------*/
1640/*--- end vg_mylibc.c ---*/
1641/*--------------------------------------------------------------------*/