blob: d0dcb57e0bb91db67e59c81cfb7f4495043fe682 [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
njn0e1b5142003-04-15 14:58:06 +000012 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 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++)
sewardj05bcdcb2003-05-18 10:05:38 +0000171 if (set->ws[i] != (UInt)(~0x0)) return False;
sewardj018f7622002-05-15 21:13:39 +0000172 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) */
njn607adfc2003-09-30 14:15:44 +0000394#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
sewardjde4a1d02002-03-22 01:27:54 +0000395
396/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000397static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000398myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
399 Bool capitalise )
400{
401# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000402 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000403 Int i, extra;
404 Int len = VG_(strlen)(str);
405
406 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000407 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000408 for (i = 0; i < len; i++)
409 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000410 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000411 }
412
413 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000414 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000415 for (i = 0; i < width; i++)
416 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000417 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000418 }
419
420 extra = width - len;
421 if (flags & VG_MSG_LJUSTIFY) {
sewardj78e3cd92002-10-22 04:45:48 +0000422 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000423 for (i = 0; i < extra; i++)
424 send(' ');
425 }
sewardj78e3cd92002-10-22 04:45:48 +0000426 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000427 for (i = 0; i < len; i++)
428 send(MAYBE_TOUPPER(str[i]));
429 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000430 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000431 for (i = 0; i < extra; i++)
432 send(' ');
433 }
434
435# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000436
437 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000438}
439
440/* Write P into the buffer according to these args:
441 * If SIGN is true, p is a signed.
442 * BASE is the base.
443 * If WITH_ZERO is true, '0' must be added.
444 * WIDTH is the width of the field.
445 */
sewardj78e3cd92002-10-22 04:45:48 +0000446static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000447myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
448{
449 Char buf[40];
450 Int ind = 0;
njn607adfc2003-09-30 14:15:44 +0000451 Int i, nc = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000452 Bool neg = False;
453 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000454 UInt ret = 0;
455
sewardjde4a1d02002-03-22 01:27:54 +0000456 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000457 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000458
459 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
460 p = - (Long)p;
461 neg = True;
462 }
463
464 if (p == 0)
465 buf[ind++] = '0';
466 else {
467 while (p > 0) {
njn607adfc2003-09-30 14:15:44 +0000468 if (flags & VG_MSG_COMMA && 10 == base &&
469 0 == (ind-nc) % 3 && 0 != ind)
470 {
471 buf[ind++] = ',';
472 nc++;
473 }
sewardjde4a1d02002-03-22 01:27:54 +0000474 buf[ind++] = digits[p % base];
475 p /= base;
njn607adfc2003-09-30 14:15:44 +0000476 }
sewardjde4a1d02002-03-22 01:27:54 +0000477 }
478
479 if (neg)
480 buf[ind++] = '-';
481
482 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
483 for(; ind < width; ind++) {
484 vg_assert(ind < 39);
485 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
486 }
487 }
488
489 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000490 ret += ind;
njn607adfc2003-09-30 14:15:44 +0000491 for (i = ind -1; i >= 0; i--) {
sewardjde4a1d02002-03-22 01:27:54 +0000492 send(buf[i]);
njn607adfc2003-09-30 14:15:44 +0000493 }
sewardjde4a1d02002-03-22 01:27:54 +0000494 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000495 for(; ind < width; ind++) {
496 ret++;
njn607adfc2003-09-30 14:15:44 +0000497 send(' '); // Never pad with zeroes on RHS -- changes the value!
sewardj78e3cd92002-10-22 04:45:48 +0000498 }
sewardjde4a1d02002-03-22 01:27:54 +0000499 }
sewardj78e3cd92002-10-22 04:45:48 +0000500 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000501}
502
503
504/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000505UInt
sewardjde4a1d02002-03-22 01:27:54 +0000506VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
507{
sewardj78e3cd92002-10-22 04:45:48 +0000508 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000509 int i;
510 int flags;
511 int width;
512 Bool is_long;
513
514 /* We assume that vargs has already been initialised by the
515 caller, using va_start, and that the caller will similarly
516 clean up with va_end.
517 */
518
519 for (i = 0; format[i] != 0; i++) {
520 if (format[i] != '%') {
521 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000522 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000523 continue;
524 }
525 i++;
526 /* A '%' has been found. Ignore a trailing %. */
527 if (format[i] == 0)
528 break;
529 if (format[i] == '%') {
530 /* `%%' is replaced by `%'. */
531 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000532 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000533 continue;
534 }
535 flags = 0;
536 is_long = False;
537 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000538 if (format[i] == '(') {
539 flags |= VG_MSG_PAREN;
540 i++;
541 }
njn607adfc2003-09-30 14:15:44 +0000542 /* If ',' follows '%', commas will be inserted. */
543 if (format[i] == ',') {
544 flags |= VG_MSG_COMMA;
545 i++;
546 }
sewardjde4a1d02002-03-22 01:27:54 +0000547 /* If '-' follows '%', justify on the left. */
548 if (format[i] == '-') {
549 flags |= VG_MSG_LJUSTIFY;
550 i++;
551 }
552 /* If '0' follows '%', pads will be inserted. */
553 if (format[i] == '0') {
554 flags |= VG_MSG_ZJUSTIFY;
555 i++;
556 }
557 /* Compute the field length. */
558 while (format[i] >= '0' && format[i] <= '9') {
559 width *= 10;
560 width += format[i++] - '0';
561 }
562 while (format[i] == 'l') {
563 i++;
564 is_long = True;
565 }
566
567 switch (format[i]) {
568 case 'd': /* %d */
569 flags |= VG_MSG_SIGNED;
570 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000571 ret += myvprintf_int64(send, flags, 10, width,
572 (ULong)(va_arg (vargs, Long)));
sewardjde4a1d02002-03-22 01:27:54 +0000573 else
sewardj78e3cd92002-10-22 04:45:48 +0000574 ret += myvprintf_int64(send, flags, 10, width,
575 (ULong)(va_arg (vargs, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000576 break;
577 case 'u': /* %u */
578 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000579 ret += myvprintf_int64(send, flags, 10, width,
580 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000581 else
sewardj78e3cd92002-10-22 04:45:48 +0000582 ret += myvprintf_int64(send, flags, 10, width,
583 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000584 break;
585 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000586 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000587 send('0');
588 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000589 ret += myvprintf_int64(send, flags, 16, width,
590 (ULong)((UInt)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000591 break;
592 case 'x': /* %x */
593 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000594 ret += myvprintf_int64(send, flags, 16, width,
595 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000596 else
sewardj78e3cd92002-10-22 04:45:48 +0000597 ret += myvprintf_int64(send, flags, 16, width,
598 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000599 break;
600 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000601 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000602 send(va_arg (vargs, int));
603 break;
604 case 's': case 'S': { /* %s */
605 char *str = va_arg (vargs, char *);
606 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000607 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000608 break;
sewardj78e3cd92002-10-22 04:45:48 +0000609 }
610 case 'y': { /* %y - print symbol */
611 Char buf[100];
612 Char *cp = buf;
613 Addr a = va_arg(vargs, Addr);
614
615 if (flags & VG_MSG_PAREN)
616 *cp++ = '(';
sewardj6e008cb2002-12-15 13:11:39 +0000617 if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
sewardj78e3cd92002-10-22 04:45:48 +0000618 if (flags & VG_MSG_PAREN) {
619 cp += VG_(strlen)(cp);
620 *cp++ = ')';
621 *cp = '\0';
622 }
623 ret += myvprintf_str(send, flags, width, buf, 0);
624 }
625
626 break;
627 }
sewardjde4a1d02002-03-22 01:27:54 +0000628 default:
629 break;
630 }
631 }
sewardj78e3cd92002-10-22 04:45:48 +0000632 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000633}
634
635
636/* A general replacement for printf(). Note that only low-level
637 debugging info should be sent via here. The official route is to
638 to use vg_message(). This interface is deprecated.
639*/
640static char myprintf_buf[100];
641static int n_myprintf_buf;
642
643static void add_to_myprintf_buf ( Char c )
644{
645 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
sewardj73cf3bc2002-11-03 03:20:15 +0000646 if (VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000647 VG_(send_bytes_to_logging_sink)(
648 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000649 }
sewardjde4a1d02002-03-22 01:27:54 +0000650 n_myprintf_buf = 0;
651 myprintf_buf[n_myprintf_buf] = 0;
652 }
653 myprintf_buf[n_myprintf_buf++] = c;
654 myprintf_buf[n_myprintf_buf] = 0;
655}
656
sewardj78e3cd92002-10-22 04:45:48 +0000657UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000658{
sewardj78e3cd92002-10-22 04:45:48 +0000659 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000660 va_list vargs;
661 va_start(vargs,format);
662
663 n_myprintf_buf = 0;
664 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000665 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000666
sewardj73cf3bc2002-11-03 03:20:15 +0000667 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000668 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000669 }
sewardjde4a1d02002-03-22 01:27:54 +0000670
671 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000672
673 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000674}
675
676
677/* A general replacement for sprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000678UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000679{
sewardj05bcdcb2003-05-18 10:05:38 +0000680 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000681 va_list vargs;
sewardj1771e172002-11-13 22:06:35 +0000682 Char *ptr = buf;
683 static void add_to_vg_sprintf_buf ( Char c )
684 {
685 *ptr++ = c;
686 }
687
sewardjde4a1d02002-03-22 01:27:54 +0000688 va_start(vargs,format);
689
sewardj78e3cd92002-10-22 04:45:48 +0000690 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000691 add_to_vg_sprintf_buf(0);
692
693 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000694
695 vg_assert(VG_(strlen)(buf) == ret);
696 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000697}
698
699
700/* ---------------------------------------------------------------------
701 Misc str* functions.
702 ------------------------------------------------------------------ */
703
704Bool VG_(isspace) ( Char c )
705{
706 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
707}
708
njn7cf0bd32002-06-08 13:36:03 +0000709Bool VG_(isdigit) ( Char c )
710{
711 return (c >= '0' && c <= '9');
712}
sewardjde4a1d02002-03-22 01:27:54 +0000713
714Int VG_(strlen) ( const Char* str )
715{
716 Int i = 0;
717 while (str[i] != 0) i++;
718 return i;
719}
720
721
722Long VG_(atoll) ( Char* str )
723{
724 Bool neg = False;
725 Long n = 0;
726 if (*str == '-') { str++; neg = True; };
727 while (*str >= '0' && *str <= '9') {
728 n = 10*n + (Long)(*str - '0');
729 str++;
730 }
731 if (neg) n = -n;
732 return n;
733}
734
735
njn25e49d8e72002-09-23 09:36:25 +0000736Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000737{
738 Bool neg = False;
739 Long n = 0;
740 if (*str == '-') { str++; neg = True; };
741 while (True) {
742 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000743 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000744 }
745 else
njn25e49d8e72002-09-23 09:36:25 +0000746 if (*str >= 'A' && *str <= 'F') {
747 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000748 }
749 else
njn25e49d8e72002-09-23 09:36:25 +0000750 if (*str >= 'a' && *str <= 'f') {
751 n = 16*n + (Long)((*str - 'a') + 10);
752 }
753 else {
754 break;
755 }
756 str++;
757 }
758 if (neg) n = -n;
759 return n;
760}
761
762Long VG_(atoll36) ( UInt base, Char* str )
763{
764 Bool neg = False;
765 Long n = 0;
766 vg_assert(base >= 2 && base <= 36);
767 if (*str == '-') { str++; neg = True; };
768 while (True) {
sewardj05bcdcb2003-05-18 10:05:38 +0000769 if (*str >= '0'
770 && *str <= (Char)('9' - (10 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000771 n = base*n + (Long)(*str - '0');
772 }
773 else
sewardj05bcdcb2003-05-18 10:05:38 +0000774 if (base > 10 && *str >= 'A'
775 && *str <= (Char)('Z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000776 n = base*n + (Long)((*str - 'A') + 10);
777 }
778 else
sewardj05bcdcb2003-05-18 10:05:38 +0000779 if (base > 10 && *str >= 'a'
780 && *str <= (Char)('z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000781 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000782 }
783 else {
784 break;
785 }
786 str++;
787 }
788 if (neg) n = -n;
789 return n;
790}
791
792
sewardjde4a1d02002-03-22 01:27:54 +0000793Char* VG_(strcat) ( Char* dest, const Char* src )
794{
795 Char* dest_orig = dest;
796 while (*dest) dest++;
797 while (*src) *dest++ = *src++;
798 *dest = 0;
799 return dest_orig;
800}
801
802
803Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
804{
805 Char* dest_orig = dest;
806 while (*dest) dest++;
807 while (*src && n > 0) { *dest++ = *src++; n--; }
808 *dest = 0;
809 return dest_orig;
810}
811
812
813Char* VG_(strpbrk) ( const Char* s, const Char* accept )
814{
815 const Char* a;
816 while (*s) {
817 a = accept;
818 while (*a)
819 if (*a++ == *s)
820 return (Char *) s;
821 s++;
822 }
823 return NULL;
824}
825
826
827Char* VG_(strcpy) ( Char* dest, const Char* src )
828{
829 Char* dest_orig = dest;
830 while (*src) *dest++ = *src++;
831 *dest = 0;
832 return dest_orig;
833}
834
835
836/* Copy bytes, not overrunning the end of dest and always ensuring
837 zero termination. */
838void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
839{
840 Int i;
841 vg_assert(ndest > 0);
842 i = 0;
843 dest[i] = 0;
844 while (True) {
845 if (src[i] == 0) return;
846 if (i >= ndest-1) return;
847 dest[i] = src[i];
848 i++;
849 dest[i] = 0;
850 }
851}
852
853
njn25e49d8e72002-09-23 09:36:25 +0000854Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000855{
njn25e49d8e72002-09-23 09:36:25 +0000856 Int i = 0;
857 while (True) {
858 if (i >= ndest) return dest; /* reached limit */
859 dest[i] = src[i];
860 if (src[i++] == 0) {
861 /* reached NUL; pad rest with zeroes as required */
862 while (i < ndest) dest[i++] = 0;
863 return dest;
864 }
865 }
sewardjde4a1d02002-03-22 01:27:54 +0000866}
867
868
869Int VG_(strcmp) ( const Char* s1, const Char* s2 )
870{
871 while (True) {
872 if (*s1 == 0 && *s2 == 0) return 0;
873 if (*s1 == 0) return -1;
874 if (*s2 == 0) return 1;
875
876 if (*(UChar*)s1 < *(UChar*)s2) return -1;
877 if (*(UChar*)s1 > *(UChar*)s2) return 1;
878
879 s1++; s2++;
880 }
881}
882
883
884Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
885{
886 while (True) {
887 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
888 if (VG_(isspace)(*s1)) return -1;
889 if (VG_(isspace)(*s2)) return 1;
890
891 if (*(UChar*)s1 < *(UChar*)s2) return -1;
892 if (*(UChar*)s1 > *(UChar*)s2) return 1;
893
894 s1++; s2++;
895 }
896}
897
898
899Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
900{
901 Int n = 0;
902 while (True) {
903 if (n >= nmax) return 0;
904 if (*s1 == 0 && *s2 == 0) return 0;
905 if (*s1 == 0) return -1;
906 if (*s2 == 0) return 1;
907
908 if (*(UChar*)s1 < *(UChar*)s2) return -1;
909 if (*(UChar*)s1 > *(UChar*)s2) return 1;
910
911 s1++; s2++; n++;
912 }
913}
914
915
916Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
917{
918 Int n = 0;
919 while (True) {
920 if (n >= nmax) return 0;
921 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
922 if (VG_(isspace)(*s1)) return -1;
923 if (VG_(isspace)(*s2)) return 1;
924
925 if (*(UChar*)s1 < *(UChar*)s2) return -1;
926 if (*(UChar*)s1 > *(UChar*)s2) return 1;
927
928 s1++; s2++; n++;
929 }
930}
931
932
933Char* VG_(strstr) ( const Char* haystack, Char* needle )
934{
sewardj3984b852002-05-12 03:00:17 +0000935 Int n;
936 if (haystack == NULL)
937 return NULL;
938 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000939 while (True) {
940 if (haystack[0] == 0)
941 return NULL;
942 if (VG_(strncmp)(haystack, needle, n) == 0)
943 return (Char*)haystack;
944 haystack++;
945 }
946}
947
948
949Char* VG_(strchr) ( const Char* s, Char c )
950{
951 while (True) {
952 if (*s == c) return (Char*)s;
953 if (*s == 0) return NULL;
954 s++;
955 }
956}
957
958
sewardj7ab2aca2002-10-20 19:40:32 +0000959void* VG_(memcpy) ( void *dest, const void *src, Int sz )
960{
961 const Char *s = (const Char *)src;
962 Char *d = (Char *)dest;
963 vg_assert(sz >= 0);
964
965 while (sz--)
966 *d++ = *s++;
967
968 return dest;
969}
970
971
972void* VG_(memset) ( void *dest, Int c, Int sz )
973{
974 Char *d = (Char *)dest;
975 vg_assert(sz >= 0);
976
977 while (sz--)
978 *d++ = c;
979
980 return dest;
981}
982
njn6d68e792003-02-24 10:49:08 +0000983Int VG_(memcmp) ( const void* s1, const void* s2, Int n )
984{
985 Int res;
njnfa4690b2003-02-24 21:43:05 +0000986 UChar a0;
987 UChar b0;
njn6d68e792003-02-24 10:49:08 +0000988 vg_assert(n >= 0);
989
990 while (n != 0) {
njnfa4690b2003-02-24 21:43:05 +0000991 a0 = ((UChar *) s1)[0];
992 b0 = ((UChar *) s2)[0];
njn6d68e792003-02-24 10:49:08 +0000993 s1 += 1;
994 s2 += 1;
995 res = a0 - b0;
996 if (res != 0)
997 return res;
998 n -= 1;
999 }
1000 return 0;
1001}
sewardj7ab2aca2002-10-20 19:40:32 +00001002
sewardjde4a1d02002-03-22 01:27:54 +00001003Char VG_(toupper) ( Char c )
1004{
1005 if (c >= 'a' && c <= 'z')
1006 return c + ('A' - 'a');
1007 else
1008 return c;
1009}
1010
1011
njn25e49d8e72002-09-23 09:36:25 +00001012/* Inline just for the wrapper VG_(strdup) below */
1013__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +00001014{
njn25e49d8e72002-09-23 09:36:25 +00001015 Int i;
1016 Int len = VG_(strlen)(s) + 1;
1017 Char* res = VG_(arena_malloc) (aid, len);
1018 for (i = 0; i < len; i++)
1019 res[i] = s[i];
1020 return res;
sewardjde4a1d02002-03-22 01:27:54 +00001021}
1022
njn25e49d8e72002-09-23 09:36:25 +00001023/* Wrapper to avoid exposing skins to ArenaId's */
1024Char* VG_(strdup) ( const Char* s )
1025{
1026 return VG_(arena_strdup) ( VG_AR_SKIN, s );
1027}
sewardjde4a1d02002-03-22 01:27:54 +00001028
1029/* ---------------------------------------------------------------------
1030 A simple string matching routine, purloined from Hugs98.
1031 `*' matches any sequence of zero or more characters
1032 `?' matches any single character exactly
1033 `\c' matches the character c only (ignoring special chars)
1034 c matches the character c only
1035 ------------------------------------------------------------------ */
1036
1037/* Keep track of recursion depth. */
1038static Int recDepth;
1039
njn4ba5a792002-09-30 10:23:54 +00001040static Bool string_match_wrk ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001041{
sewardje54b69d2003-07-06 01:14:42 +00001042 vg_assert(recDepth >= 0 && recDepth < 500);
sewardjde4a1d02002-03-22 01:27:54 +00001043 recDepth++;
1044 for (;;) {
1045 switch (*pat) {
1046 case '\0' : return (*str=='\0');
1047 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001048 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001049 recDepth--;
1050 return True;
1051 }
1052 } while (*str++);
1053 recDepth--;
1054 return False;
1055 case '?' : if (*str++=='\0') {
1056 recDepth--;
1057 return False;
1058 }
1059 pat++;
1060 break;
1061 case '\\' : if (*++pat == '\0') {
1062 recDepth--;
1063 return False; /* spurious trailing \ in pattern */
1064 }
1065 /* falls through to ... */
1066 default : if (*pat++ != *str++) {
1067 recDepth--;
1068 return False;
1069 }
1070 break;
1071 }
1072 }
1073}
1074
njn4ba5a792002-09-30 10:23:54 +00001075Bool VG_(string_match) ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001076{
1077 Bool b;
1078 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001079 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001080 /*
1081 VG_(printf)("%s %s %s\n",
1082 b?"TRUE ":"FALSE", pat, str);
1083 */
1084 return b;
1085}
1086
1087
1088/* ---------------------------------------------------------------------
1089 Assertery.
1090 ------------------------------------------------------------------ */
1091
njne427a662002-10-02 11:08:25 +00001092__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001093static void report_and_quit ( const Char* report )
njne427a662002-10-02 11:08:25 +00001094{
1095 VG_(pp_sched_status)();
sewardj366ee1e2003-04-26 22:36:42 +00001096 VG_(printf)("\n");
1097 VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
1098 VG_(printf)("It contains workarounds to several common problems.\n");
1099 VG_(printf)("\n");
1100 VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
1101 report);
1102 VG_(printf)("In the bug report, send all the above text, the valgrind\n");
sewardj96330bd2003-04-27 23:46:21 +00001103 VG_(printf)("version, and what Linux distro you are using. Thanks.\n\n");
njne427a662002-10-02 11:08:25 +00001104 VG_(shutdown_logging)();
1105 VG_(exit)(1);
1106}
1107
1108__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001109static void assert_fail ( const Char* expr, const Char* name, const Char* report,
1110 const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001111{
sewardj018f7622002-05-15 21:13:39 +00001112 static Bool entered = False;
1113 if (entered)
1114 VG_(exit)(2);
1115 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001116 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001117 name, file, line, fn, expr );
1118 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001119}
1120
daywalker3222e0a2003-09-18 01:39:50 +00001121void VG_(skin_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001122{
njnd04b7c62002-10-03 14:05:52 +00001123 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001124 file, line, fn);
1125}
1126
daywalker3222e0a2003-09-18 01:39:50 +00001127void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
njne427a662002-10-02 11:08:25 +00001128{
1129 assert_fail(expr, "valgrind", VG_EMAIL_ADDR, file, line, fn);
1130}
1131
1132__attribute__ ((noreturn))
1133static void panic ( Char* name, Char* report, Char* str )
1134{
1135 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001136 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
njne427a662002-10-02 11:08:25 +00001137 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001138}
1139
njne427a662002-10-02 11:08:25 +00001140void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001141{
njne427a662002-10-02 11:08:25 +00001142 panic("valgrind", VG_EMAIL_ADDR, str);
njn25e49d8e72002-09-23 09:36:25 +00001143}
1144
njne427a662002-10-02 11:08:25 +00001145void VG_(skin_panic) ( Char* str )
1146{
njnd04b7c62002-10-03 14:05:52 +00001147 panic(VG_(details).name, VG_(details).bug_reports_to, str);
njne427a662002-10-02 11:08:25 +00001148}
sewardjde4a1d02002-03-22 01:27:54 +00001149
njn13f02932003-04-30 20:23:58 +00001150
sewardjde4a1d02002-03-22 01:27:54 +00001151/* ---------------------------------------------------------------------
1152 Primitive support for reading files.
1153 ------------------------------------------------------------------ */
1154
1155/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001156Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1157{
sewardjde4a1d02002-03-22 01:27:54 +00001158 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001159
njn25e49d8e72002-09-23 09:36:25 +00001160 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001161 /* This gets a segmentation fault if pathname isn't a valid file.
1162 I don't know why. It seems like the call to open is getting
1163 intercepted and messed with by glibc ... */
1164 /* fd = open( pathname, O_RDONLY ); */
1165 /* ... so we go direct to the horse's mouth, which seems to work
1166 ok: */
njn25e49d8e72002-09-23 09:36:25 +00001167 fd = vg_do_syscall3(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001168 /* VG_(printf)("result = %d\n", fd); */
njn13f02932003-04-30 20:23:58 +00001169 if (VG_(is_kerror)(fd)) fd = -1;
njn4f9c9342002-04-29 16:03:24 +00001170 return fd;
1171}
sewardjde4a1d02002-03-22 01:27:54 +00001172
1173void VG_(close) ( Int fd )
1174{
1175 vg_do_syscall1(__NR_close, fd);
1176}
1177
1178
1179Int VG_(read) ( Int fd, void* buf, Int count)
1180{
1181 Int res;
1182 /* res = read( fd, buf, count ); */
1183 res = vg_do_syscall3(__NR_read, fd, (UInt)buf, count);
1184 if (VG_(is_kerror)(res)) res = -1;
1185 return res;
1186}
1187
1188Int VG_(write) ( Int fd, void* buf, Int count)
1189{
1190 Int res;
1191 /* res = write( fd, buf, count ); */
1192 res = vg_do_syscall3(__NR_write, fd, (UInt)buf, count);
1193 if (VG_(is_kerror)(res)) res = -1;
1194 return res;
1195}
1196
sewardjb3586202002-05-09 17:38:13 +00001197Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1198{
1199 Int res;
1200 res = vg_do_syscall2(__NR_stat, (UInt)file_name, (UInt)buf);
njn41557122002-10-14 09:25:37 +00001201 return VG_(is_kerror)(res) ? (-1) : 0;
1202}
1203
1204Int VG_(rename) ( Char* old_name, Char* new_name )
1205{
1206 Int res;
1207 res = vg_do_syscall2(__NR_rename, (UInt)old_name, (UInt)new_name);
1208 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001209}
1210
njn4aca2d22002-10-04 10:29:38 +00001211Int VG_(unlink) ( Char* file_name )
1212{
1213 Int res;
1214 res = vg_do_syscall1(__NR_unlink, (UInt)file_name);
njn41557122002-10-14 09:25:37 +00001215 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001216}
1217
njn13f02932003-04-30 20:23:58 +00001218/* Nb: we do not allow the Linux extension which malloc()s memory for the
1219 buffer if buf==NULL, because we don't want Linux calling malloc() */
1220Char* VG_(getcwd) ( Char* buf, Int size )
1221{
1222 Int res;
1223 vg_assert(buf != NULL);
1224 res = vg_do_syscall2(__NR_getcwd, (UInt)buf, (UInt)size);
1225 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1226}
1227
njn99ccf082003-09-30 13:51:23 +00001228/* Alternative version that does allocate the memory. Easier to use. */
1229Bool VG_(getcwd_alloc) ( Char** out )
1230{
1231 UInt size = 4;
1232
1233 *out = NULL;
1234 while (True) {
1235 *out = VG_(malloc)(size);
1236 if (NULL == VG_(getcwd)(*out, size)) {
1237 VG_(free)(*out);
1238 if (size > 65535)
1239 return False;
1240 size *= 2;
1241 } else {
1242 return True;
1243 }
1244 }
1245}
1246
njn13f02932003-04-30 20:23:58 +00001247
1248/* ---------------------------------------------------------------------
1249 Misc functions looking for a proper home.
1250 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001251
1252/* We do getenv without libc's help by snooping around in
njn25e49d8e72002-09-23 09:36:25 +00001253 VG_(client_envp) as determined at startup time. */
sewardjde4a1d02002-03-22 01:27:54 +00001254Char* VG_(getenv) ( Char* varname )
1255{
1256 Int i, n;
1257 n = VG_(strlen)(varname);
1258 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1259 Char* s = VG_(client_envp)[i];
1260 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1261 return & s[n+1];
1262 }
1263 }
1264 return NULL;
1265}
1266
sewardj4cf05692002-10-27 20:28:29 +00001267
sewardjde4a1d02002-03-22 01:27:54 +00001268/* You'd be amazed how many places need to know the current pid. */
1269Int VG_(getpid) ( void )
1270{
1271 Int res;
1272 /* res = getpid(); */
1273 res = vg_do_syscall0(__NR_getpid);
1274 return res;
1275}
1276
sewardj4cf05692002-10-27 20:28:29 +00001277Int VG_(getppid) ( void )
1278{
1279 Int res;
1280 res = vg_do_syscall0(__NR_getppid);
1281 return res;
1282}
1283
1284
sewardje6a25242002-04-21 22:03:07 +00001285/* Return -1 if error, else 0. NOTE does not indicate return code of
1286 child! */
1287Int VG_(system) ( Char* cmd )
1288{
1289 Int pid, res;
1290 void* environ[1] = { NULL };
1291 if (cmd == NULL)
1292 return 1;
1293 pid = vg_do_syscall0(__NR_fork);
1294 if (VG_(is_kerror)(pid))
1295 return -1;
1296 if (pid == 0) {
1297 /* child */
1298 Char* argv[4];
1299 argv[0] = "/bin/sh";
1300 argv[1] = "-c";
1301 argv[2] = cmd;
1302 argv[3] = 0;
1303 (void)vg_do_syscall3(__NR_execve,
1304 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
1305 /* If we're still alive here, execve failed. */
1306 return -1;
1307 } else {
1308 /* parent */
1309 res = vg_do_syscall3(__NR_waitpid, pid, (UInt)NULL, 0);
1310 if (VG_(is_kerror)(res)) {
1311 return -1;
1312 } else {
1313 return 0;
1314 }
1315 }
1316}
1317
1318
sewardjde4a1d02002-03-22 01:27:54 +00001319/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001320 Support for a millisecond-granularity counter using RDTSC.
1321 ------------------------------------------------------------------ */
1322
1323static __inline__ ULong do_rdtsc_insn ( void )
1324{
1325 ULong x;
1326 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1327 return x;
1328}
1329
1330/* 0 = pre-calibration, 1 = calibration, 2 = running */
1331static Int rdtsc_calibration_state = 0;
1332static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1333
1334static struct vki_timeval rdtsc_cal_start_timeval;
1335static struct vki_timeval rdtsc_cal_end_timeval;
1336
1337static ULong rdtsc_cal_start_raw;
1338static ULong rdtsc_cal_end_raw;
1339
1340UInt VG_(read_millisecond_timer) ( void )
1341{
1342 ULong rdtsc_now;
njne7442cf2003-09-30 14:03:21 +00001343 // If called before rdtsc setup completed (eg. from SK_(pre_clo_init)())
1344 // just return 0.
1345 if (rdtsc_calibration_state < 2) return 0;
sewardj5f07b662002-04-23 16:52:51 +00001346 rdtsc_now = do_rdtsc_insn();
1347 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1348 rdtsc_now -= rdtsc_cal_end_raw;
1349 rdtsc_now /= rdtsc_ticks_per_millisecond;
1350 return (UInt)rdtsc_now;
1351}
1352
1353
1354void VG_(start_rdtsc_calibration) ( void )
1355{
1356 Int res;
1357 vg_assert(rdtsc_calibration_state == 0);
1358 rdtsc_calibration_state = 1;
1359 rdtsc_cal_start_raw = do_rdtsc_insn();
1360 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1361 (UInt)NULL);
1362 vg_assert(!VG_(is_kerror)(res));
1363}
1364
1365void VG_(end_rdtsc_calibration) ( void )
1366{
1367 Int res, loops;
1368 ULong cpu_clock_MHZ;
1369 ULong cal_clock_ticks;
1370 ULong cal_wallclock_microseconds;
1371 ULong wallclock_start_microseconds;
1372 ULong wallclock_end_microseconds;
1373 struct vki_timespec req;
1374 struct vki_timespec rem;
1375
1376 vg_assert(rdtsc_calibration_state == 1);
1377 rdtsc_calibration_state = 2;
1378
1379 /* Try and delay for 20 milliseconds, so that we can at least have
1380 some minimum level of accuracy. */
1381 req.tv_sec = 0;
1382 req.tv_nsec = 20 * 1000 * 1000;
1383 loops = 0;
1384 while (True) {
1385 res = VG_(nanosleep)(&req, &rem);
1386 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1387 if (res == 0)
1388 break;
1389 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1390 break;
1391 req = rem;
1392 loops++;
1393 if (loops > 100)
njne427a662002-10-02 11:08:25 +00001394 VG_(core_panic)("calibration nanosleep loop failed?!");
sewardj5f07b662002-04-23 16:52:51 +00001395 }
1396
1397 /* Now read both timers, and do the Math. */
1398 rdtsc_cal_end_raw = do_rdtsc_insn();
1399 res = vg_do_syscall2(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1400 (UInt)NULL);
1401
1402 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1403 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1404
1405 wallclock_start_microseconds
1406 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1407 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1408 wallclock_end_microseconds
1409 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1410 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1411 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1412 cal_wallclock_microseconds
1413 = wallclock_end_microseconds - wallclock_start_microseconds;
1414
1415 /* Since we just nanoslept for 20 ms ... */
1416 vg_assert(cal_wallclock_microseconds >= 20000);
1417
1418 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1419 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1420 ticks-per-millisecond value. */
1421 if (0)
1422 VG_(printf)("%lld ticks in %lld microseconds\n",
1423 cal_clock_ticks, cal_wallclock_microseconds );
1424
1425 rdtsc_ticks_per_millisecond
1426 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1427 cpu_clock_MHZ
1428 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1429 if (VG_(clo_verbosity) >= 1)
1430 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1431 (UInt)cpu_clock_MHZ);
sewardj09c55fd2002-06-13 11:37:41 +00001432 if (cpu_clock_MHZ < 50 || cpu_clock_MHZ > 10000)
njne427a662002-10-02 11:08:25 +00001433 VG_(core_panic)("end_rdtsc_calibration: "
sewardj09c55fd2002-06-13 11:37:41 +00001434 "estimated CPU MHz outside range 50 .. 10000");
sewardj5f07b662002-04-23 16:52:51 +00001435 /* Paranoia about division by zero later. */
1436 vg_assert(rdtsc_ticks_per_millisecond != 0);
1437 if (0)
1438 VG_(printf)("ticks per millisecond %llu\n",
1439 rdtsc_ticks_per_millisecond);
1440}
1441
1442
1443
1444/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001445 Primitive support for bagging memory via mmap.
1446 ------------------------------------------------------------------ */
1447
sewardje9047952002-06-05 20:28:33 +00001448void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001449{
1450 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001451 void* p;
1452 p = VG_(mmap)( 0, nBytes,
1453 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1454 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001455 if (p != ((void*)(-1))) {
1456 tot_alloc += (UInt)nBytes;
1457 if (0)
sewardje9047952002-06-05 20:28:33 +00001458 VG_(printf)(
1459 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1460 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001461 return p;
1462 }
sewardj7c2020b2002-09-30 22:56:03 +00001463
njn25e49d8e72002-09-23 09:36:25 +00001464 VG_(printf)("\n");
daywalkerb1db1232003-09-26 00:26:07 +00001465 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %d bytes failed.\n",
1466 who, nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001467 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1468 tot_alloc);
1469 VG_(printf)("\n");
1470 VG_(printf)("This may mean that you have run out of swap space,\n");
1471 VG_(printf)("since running programs on valgrind increases their memory\n");
1472 VG_(printf)("usage at least 3 times. You might want to use 'top'\n");
1473 VG_(printf)("to determine whether you really have run out of swap.\n");
1474 VG_(printf)("If so, you may be able to work around it by adding a\n");
1475 VG_(printf)("temporary swap file -- this is easier than finding a\n");
1476 VG_(printf)("new swap partition. Go ask your sysadmin(s) [politely!]\n");
1477 VG_(printf)("\n");
1478 VG_(printf)("VG_(get_memory_from_mmap): out of memory! Fatal! Bye!\n");
1479 VG_(printf)("\n");
1480 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001481}
1482
njn25e49d8e72002-09-23 09:36:25 +00001483/* ---------------------------------------------------------------------
1484 Generally useful...
1485 ------------------------------------------------------------------ */
1486
1487Int VG_(log2) ( Int x )
1488{
1489 Int i;
1490 /* Any more than 32 and we overflow anyway... */
1491 for (i = 0; i < 32; i++) {
1492 if (1 << i == x) return i;
1493 }
1494 return -1;
1495}
1496
1497
njnd3b0c5f2003-09-30 14:43:54 +00001498// Generic shell sort. Like stdlib.h's qsort().
1499void VG_(ssort)( void* base, UInt nmemb, UInt size,
1500 Int (*compar)(void*, void*) )
1501{
1502 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1503 9841, 29524, 88573, 265720,
1504 797161, 2391484 };
1505 Int lo = 0;
1506 Int hi = nmemb-1;
1507 Int i, j, h, bigN, hp;
1508
1509 bigN = hi - lo + 1; if (bigN < 2) return;
1510 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1511 vg_assert(0 <= hp && hp < 14);
1512
1513 #define SORT \
1514 for ( ; hp >= 0; hp--) { \
1515 h = incs[hp]; \
1516 i = lo + h; \
1517 while (1) { \
1518 if (i > hi) break; \
1519 ASSIGN(v,0, a,i); \
1520 j = i; \
1521 while (COMPAR(a,(j-h), v,0) > 0) { \
1522 ASSIGN(a,j, a,(j-h)); \
1523 j = j - h; \
1524 if (j <= (lo + h - 1)) break; \
1525 } \
1526 ASSIGN(a,j, v,0); \
1527 i++; \
1528 } \
1529 }
1530
1531 // Specialised cases
1532 if (sizeof(UInt) == size) {
1533
1534 #define ASSIGN(dst, dsti, src, srci) \
1535 (dst)[(dsti)] = (src)[(srci)];
1536
1537 #define COMPAR(dst, dsti, src, srci) \
1538 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1539
1540 UInt* a = (UInt*)base;
1541 UInt v[1];
1542
1543 SORT;
1544
1545 } else if (sizeof(UShort) == size) {
1546 UShort* a = (UShort*)base;
1547 UShort v[1];
1548
1549 SORT;
1550
1551 } else if (sizeof(UChar) == size) {
1552 UChar* a = (UChar*)base;
1553 UChar v[1];
1554
1555 SORT;
1556
1557 #undef ASSIGN
1558 #undef COMPAR
1559
1560 // General case
1561 } else {
1562 void* a = (void*)base;
1563 Char vc[size]; // will be at least 'size' bytes
1564 void* v = (void*)vc;
1565
1566 #define ASSIGN(dst, dsti, src, srci) \
1567 VG_(memcpy)( (void*)((dst) + size*(dsti)), \
1568 (void*)((src) + size*(srci)), (size) );
1569
1570 #define COMPAR(dst, dsti, src, srci) \
1571 compar( (void*)((dst) + size*(dsti)), (void*)((src) + size*(srci)) )
1572
1573 SORT;
1574
1575 #undef ASSIGN
1576 #undef COMPAR
1577 }
1578 #undef SORT
1579}
1580
sewardj73cf3bc2002-11-03 03:20:15 +00001581/* ---------------------------------------------------------------------
1582 Gruesome hackery for connecting to a logging server over the network.
1583 This is all very Linux-kernel specific.
1584 ------------------------------------------------------------------ */
1585
1586/* Various needed constants from the kernel iface (2.4),
1587 /usr/src/linux-2.4.9-31 */
1588
1589/* kernel, ./include/linux/net.h */
1590#define SYS_SOCKET 1 /* sys_socket(2) */
1591#define SYS_CONNECT 3 /* sys_connect(2) */
1592#define SYS_SEND 9 /* sys_send(2) */
1593
1594typedef UInt __u32;
1595
1596/* Internet address. */
1597struct vki_in_addr {
1598 __u32 s_addr;
1599};
1600
1601/* kernel, include/linux/socket.h */
1602typedef unsigned short vki_sa_family_t;
1603#define AF_INET 2 /* Internet IP Protocol */
sewardj570f8902002-11-03 11:44:36 +00001604#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
sewardj73cf3bc2002-11-03 03:20:15 +00001605
1606/* kernel, ./include/asm-i386/socket.h */
1607#define SOCK_STREAM 1 /* stream (connection) socket */
1608
1609/* kernel, /usr/src/linux-2.4.9-31/linux/include/in.h */
1610/* Structure describing an Internet (IP) socket address. */
1611#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
1612struct vki_sockaddr_in {
1613 vki_sa_family_t sin_family; /* Address family */
1614 unsigned short int sin_port; /* Port number */
1615 struct vki_in_addr sin_addr; /* Internet address */
1616
1617 /* Pad to size of `struct sockaddr'. */
1618 unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
1619 sizeof(unsigned short int) -
1620 sizeof(struct vki_in_addr)];
1621};
1622
1623
1624static
1625Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1626
1627static
1628Int my_socket ( Int domain, Int type, Int protocol );
1629
1630static
1631Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1632 Int addrlen );
1633
1634static
1635UInt my_htonl ( UInt x )
1636{
1637 return
1638 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1639 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1640}
1641
1642static
1643UShort my_htons ( UShort x )
1644{
1645 return
1646 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1647}
1648
1649
1650/* The main function.
1651
1652 Supplied string contains either an ip address "192.168.0.1" or
1653 an ip address and port pair, "192.168.0.1:1500". Parse these,
1654 and return:
1655 -1 if there is a parse error
1656 -2 if no parse error, but specified host:port cannot be opened
1657 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001658 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001659*/
1660Int VG_(connect_via_socket)( UChar* str )
1661{
1662 Int sd, res;
1663 struct vki_sockaddr_in servAddr;
1664 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001665 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001666 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1667 if (!ok)
1668 return -1;
1669
1670 if (0)
1671 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1672 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1673 (ip >> 8) & 0xFF, ip & 0xFF,
1674 (UInt)port );
1675
1676 servAddr.sin_family = AF_INET;
1677 servAddr.sin_addr.s_addr = my_htonl(ip);
1678 servAddr.sin_port = my_htons(port);
1679
1680 /* create socket */
1681 sd = my_socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1682 if (sd < 0) {
1683 /* this shouldn't happen ... nevertheless */
1684 return -2;
1685 }
1686
1687 /* connect to server */
1688 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1689 sizeof(servAddr));
1690 if (res < 0) {
1691 /* connection failed */
1692 return -2;
1693 }
1694
1695 return sd;
1696}
1697
1698
1699/* Let d = one or more digits. Accept either:
1700 d.d.d.d or d.d.d.d:d
1701*/
1702Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1703{
1704# define GET_CH ((*str) ? (*str++) : 0)
1705 UInt ipa, i, j, c, any;
1706 ipa = 0;
1707 for (i = 0; i < 4; i++) {
1708 j = 0;
1709 any = 0;
1710 while (1) {
1711 c = GET_CH;
1712 if (c < '0' || c > '9') break;
1713 j = 10 * j + (int)(c - '0');
1714 any = 1;
1715 }
1716 if (any == 0 || j > 255) goto syntaxerr;
1717 ipa = (ipa << 8) + j;
1718 if (i <= 2 && c != '.') goto syntaxerr;
1719 }
1720 if (c == 0 || c == ':')
1721 *ip_addr = ipa;
1722 if (c == 0) goto ok;
1723 if (c != ':') goto syntaxerr;
1724 j = 0;
1725 any = 0;
1726 while (1) {
1727 c = GET_CH;
1728 if (c < '0' || c > '9') break;
1729 j = j * 10 + (int)(c - '0');
1730 any = 1;
1731 if (j > 65535) goto syntaxerr;
1732 }
1733 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001734 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001735 *port = (UShort)j;
1736 ok:
1737 return 1;
1738 syntaxerr:
1739 return 0;
1740# undef GET_CH
1741}
1742
1743
1744static
1745Int my_socket ( Int domain, Int type, Int protocol )
1746{
1747 Int res;
1748 UInt args[3];
1749 args[0] = domain;
1750 args[1] = type;
1751 args[2] = protocol;
1752 res = vg_do_syscall2(__NR_socketcall, SYS_SOCKET, (UInt)&args);
1753 if (VG_(is_kerror)(res))
1754 res = -1;
1755 return res;
1756}
1757
1758static
1759Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1760 Int addrlen )
1761{
1762 Int res;
1763 UInt args[3];
1764 args[0] = sockfd;
1765 args[1] = (UInt)serv_addr;
1766 args[2] = addrlen;
1767 res = vg_do_syscall2(__NR_socketcall, SYS_CONNECT, (UInt)&args);
1768 if (VG_(is_kerror)(res))
1769 res = -1;
1770 return res;
1771}
1772
1773Int VG_(write_socket)( Int sd, void *msg, Int count )
1774{
1775 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001776
1777 /* Requests not to send SIGPIPE on errors on stream oriented
1778 sockets when the other end breaks the connection. The EPIPE
1779 error is still returned. */
1780 Int flags = MSG_NOSIGNAL;
1781
sewardj73cf3bc2002-11-03 03:20:15 +00001782 Int res;
1783 UInt args[4];
1784 args[0] = sd;
1785 args[1] = (UInt)msg;
1786 args[2] = count;
1787 args[3] = flags;
1788 res = vg_do_syscall2(__NR_socketcall, SYS_SEND, (UInt)&args);
1789 if (VG_(is_kerror)(res))
1790 res = -1;
1791 return res;
1792}
1793
sewardjde4a1d02002-03-22 01:27:54 +00001794
1795/*--------------------------------------------------------------------*/
1796/*--- end vg_mylibc.c ---*/
1797/*--------------------------------------------------------------------*/