blob: 5931db9422ceb038662671a4776c704d3f6b366a [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
sewardjde4a1d02002-03-22 01:27:54 +000035/* ---------------------------------------------------------------------
36 Wrappers around system calls, and other stuff, to do with signals.
37 ------------------------------------------------------------------ */
38
39/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
40 success and -1 on error.
41*/
42Int VG_(ksigfillset)( vki_ksigset_t* set )
43{
44 Int i;
45 if (set == NULL)
46 return -1;
47 for (i = 0; i < VKI_KNSIG_WORDS; i++)
48 set->ws[i] = 0xFFFFFFFF;
49 return 0;
50}
51
52Int VG_(ksigemptyset)( vki_ksigset_t* set )
53{
54 Int i;
55 if (set == NULL)
56 return -1;
57 for (i = 0; i < VKI_KNSIG_WORDS; i++)
58 set->ws[i] = 0x0;
59 return 0;
60}
61
sewardjb48e5002002-05-13 00:16:03 +000062Bool VG_(kisemptysigset)( vki_ksigset_t* set )
63{
64 Int i;
65 vg_assert(set != NULL);
66 for (i = 0; i < VKI_KNSIG_WORDS; i++)
67 if (set->ws[i] != 0x0) return False;
68 return True;
69}
70
sewardj018f7622002-05-15 21:13:39 +000071Bool VG_(kisfullsigset)( vki_ksigset_t* set )
72{
73 Int i;
74 vg_assert(set != NULL);
75 for (i = 0; i < VKI_KNSIG_WORDS; i++)
sewardj05bcdcb2003-05-18 10:05:38 +000076 if (set->ws[i] != (UInt)(~0x0)) return False;
sewardj018f7622002-05-15 21:13:39 +000077 return True;
78}
79
80
sewardjde4a1d02002-03-22 01:27:54 +000081Int VG_(ksigaddset)( vki_ksigset_t* set, Int signum )
82{
83 if (set == NULL)
84 return -1;
njn25e49d8e72002-09-23 09:36:25 +000085 if (signum < 1 || signum > VKI_KNSIG)
sewardjde4a1d02002-03-22 01:27:54 +000086 return -1;
87 signum--;
88 set->ws[signum / VKI_KNSIG_BPW] |= (1 << (signum % VKI_KNSIG_BPW));
89 return 0;
90}
91
sewardj018f7622002-05-15 21:13:39 +000092Int VG_(ksigdelset)( vki_ksigset_t* set, Int signum )
93{
94 if (set == NULL)
95 return -1;
njn25e49d8e72002-09-23 09:36:25 +000096 if (signum < 1 || signum > VKI_KNSIG)
sewardj018f7622002-05-15 21:13:39 +000097 return -1;
98 signum--;
99 set->ws[signum / VKI_KNSIG_BPW] &= ~(1 << (signum % VKI_KNSIG_BPW));
100 return 0;
101}
102
sewardjde4a1d02002-03-22 01:27:54 +0000103Int VG_(ksigismember) ( vki_ksigset_t* set, Int signum )
104{
105 if (set == NULL)
sewardjb48e5002002-05-13 00:16:03 +0000106 return 0;
njn25e49d8e72002-09-23 09:36:25 +0000107 if (signum < 1 || signum > VKI_KNSIG)
sewardjb48e5002002-05-13 00:16:03 +0000108 return 0;
sewardjde4a1d02002-03-22 01:27:54 +0000109 signum--;
110 if (1 & ((set->ws[signum / VKI_KNSIG_BPW]) >> (signum % VKI_KNSIG_BPW)))
111 return 1;
112 else
113 return 0;
114}
115
116
sewardjb48e5002002-05-13 00:16:03 +0000117/* Add all signals in src to dst. */
118void VG_(ksigaddset_from_set)( vki_ksigset_t* dst, vki_ksigset_t* src )
119{
120 Int i;
121 vg_assert(dst != NULL && src != NULL);
122 for (i = 0; i < VKI_KNSIG_WORDS; i++)
123 dst->ws[i] |= src->ws[i];
124}
125
126/* Remove all signals in src from dst. */
127void VG_(ksigdelset_from_set)( vki_ksigset_t* dst, vki_ksigset_t* src )
128{
129 Int i;
130 vg_assert(dst != NULL && src != NULL);
131 for (i = 0; i < VKI_KNSIG_WORDS; i++)
132 dst->ws[i] &= ~(src->ws[i]);
133}
134
135
sewardjde4a1d02002-03-22 01:27:54 +0000136/* The functions sigaction, sigprocmask, sigpending and sigsuspend
137 return 0 on success and -1 on error.
138*/
139Int VG_(ksigprocmask)( Int how,
140 const vki_ksigset_t* set,
141 vki_ksigset_t* oldset)
142{
143 Int res
jsgf855d93d2003-10-13 22:26:55 +0000144 = VG_(do_syscall)(__NR_rt_sigprocmask,
145 how, (UInt)set, (UInt)oldset,
146 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
sewardjde4a1d02002-03-22 01:27:54 +0000147 return VG_(is_kerror)(res) ? -1 : 0;
148}
149
150
151Int VG_(ksigaction) ( Int signum,
152 const vki_ksigaction* act,
153 vki_ksigaction* oldact)
154{
155 Int res
jsgf855d93d2003-10-13 22:26:55 +0000156 = VG_(do_syscall)(__NR_rt_sigaction,
157 signum, (UInt)act, (UInt)oldact,
158 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
sewardj018f7622002-05-15 21:13:39 +0000159 /* VG_(printf)("res = %d\n",res); */
sewardjde4a1d02002-03-22 01:27:54 +0000160 return VG_(is_kerror)(res) ? -1 : 0;
161}
162
163
164Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss )
165{
166 Int res
jsgf855d93d2003-10-13 22:26:55 +0000167 = VG_(do_syscall)(__NR_sigaltstack, (UInt)ss, (UInt)oss);
sewardjde4a1d02002-03-22 01:27:54 +0000168 return VG_(is_kerror)(res) ? -1 : 0;
169}
170
jsgf855d93d2003-10-13 22:26:55 +0000171Int VG_(ksigtimedwait)( const vki_ksigset_t *set, vki_ksiginfo_t *info,
172 const struct vki_timespec *timeout )
173{
174 Int res = VG_(do_syscall)(__NR_rt_sigtimedwait, set, info, timeout, sizeof(*set));
175
176 return VG_(is_kerror)(res) ? -1 : res;
177}
sewardjde4a1d02002-03-22 01:27:54 +0000178
179Int VG_(ksignal)(Int signum, void (*sighandler)(Int))
180{
181 Int res;
182 vki_ksigaction sa;
183 sa.ksa_handler = sighandler;
184 sa.ksa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
185 sa.ksa_restorer = NULL;
186 res = VG_(ksigemptyset)( &sa.ksa_mask );
187 vg_assert(res == 0);
jsgf855d93d2003-10-13 22:26:55 +0000188 res = VG_(do_syscall)(__NR_rt_sigaction,
189 signum, (UInt)(&sa), (UInt)NULL,
190 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
sewardjde4a1d02002-03-22 01:27:54 +0000191 return VG_(is_kerror)(res) ? -1 : 0;
192}
193
194
sewardjdcaf3122002-09-30 23:12:33 +0000195Int VG_(kkill)( Int pid, Int signo )
sewardj018f7622002-05-15 21:13:39 +0000196{
jsgf855d93d2003-10-13 22:26:55 +0000197 Int res = VG_(do_syscall)(__NR_kill, pid, signo);
sewardj018f7622002-05-15 21:13:39 +0000198 return VG_(is_kerror)(res) ? -1 : 0;
199}
200
201
jsgf855d93d2003-10-13 22:26:55 +0000202Int VG_(ktkill)( Int tid, Int signo )
203{
204 Int ret = -VKI_ENOSYS;
205
206#ifdef __NR_tkill
207 ret = VG_(do_syscall)(__NR_tkill, tid, signo);
208#endif /* __NR_tkill */
209
210 if (ret == -VKI_ENOSYS)
211 ret = VG_(do_syscall)(__NR_kill, tid, signo);
212
213 return VG_(is_kerror)(ret) ? -1 : 0;
214}
215
sewardjdcaf3122002-09-30 23:12:33 +0000216Int VG_(ksigpending) ( vki_ksigset_t* set )
sewardjefbfcdf2002-06-19 17:35:45 +0000217{
jsgf855d93d2003-10-13 22:26:55 +0000218 Int res = VG_(do_syscall)(__NR_sigpending, (UInt)set);
sewardjefbfcdf2002-06-19 17:35:45 +0000219 return VG_(is_kerror)(res) ? -1 : 0;
220}
221
jsgf855d93d2003-10-13 22:26:55 +0000222Int VG_(waitpid)(Int pid, Int *status, Int options)
223{
224 Int ret = VG_(do_syscall)(__NR_wait4, pid, status, options, NULL);
225
226 return VG_(is_kerror)(ret) ? -1 : ret;
227}
228
229Int VG_(gettid)(void)
230{
231 Int ret;
232
233 ret = VG_(do_syscall)(__NR_gettid);
234
235 if (ret == -VKI_ENOSYS)
236 ret = VG_(do_syscall)(__NR_getpid);
237
238 return ret;
239}
240
241
sewardjefbfcdf2002-06-19 17:35:45 +0000242
sewardjde4a1d02002-03-22 01:27:54 +0000243/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000244 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000245 ------------------------------------------------------------------ */
246
247/* Returns -1 on failure. */
248void* VG_(mmap)( void* start, UInt length,
249 UInt prot, UInt flags, UInt fd, UInt offset)
250{
251 Int res;
252 UInt args[6];
253 args[0] = (UInt)start;
254 args[1] = length;
255 args[2] = prot;
256 args[3] = flags;
257 args[4] = fd;
258 args[5] = offset;
jsgf855d93d2003-10-13 22:26:55 +0000259 res = VG_(do_syscall)(__NR_mmap, (UInt)(&(args[0])) );
sewardjde4a1d02002-03-22 01:27:54 +0000260 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
261}
262
263/* Returns -1 on failure. */
264Int VG_(munmap)( void* start, Int length )
265{
jsgf855d93d2003-10-13 22:26:55 +0000266 Int res = VG_(do_syscall)(__NR_munmap, (UInt)start, (UInt)length );
sewardjde4a1d02002-03-22 01:27:54 +0000267 return VG_(is_kerror)(res) ? -1 : 0;
268}
269
270void VG_(exit)( Int status )
271{
jsgf855d93d2003-10-13 22:26:55 +0000272 (void)VG_(do_syscall)(__NR_exit_group, (UInt)status );
273 (void)VG_(do_syscall)(__NR_exit, (UInt)status );
sewardjde4a1d02002-03-22 01:27:54 +0000274 /* Why are we still alive here? */
275 /*NOTREACHED*/
jsgf855d93d2003-10-13 22:26:55 +0000276 *(volatile Int *)0 = 'x';
sewardjde4a1d02002-03-22 01:27:54 +0000277 vg_assert(2+2 == 5);
278}
279
sewardj2e93c502002-04-12 11:12:52 +0000280/* Returns -1 on error. */
281Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
282{
jsgf855d93d2003-10-13 22:26:55 +0000283 Int res = VG_(do_syscall)(__NR_fcntl, fd, cmd, arg);
sewardj2e93c502002-04-12 11:12:52 +0000284 return VG_(is_kerror)(res) ? -1 : res;
285}
286
287/* Returns -1 on error. */
288Int VG_(select)( Int n,
289 vki_fd_set* readfds,
290 vki_fd_set* writefds,
291 vki_fd_set* exceptfds,
292 struct vki_timeval * timeout )
293{
294 Int res;
295 UInt args[5];
296 args[0] = n;
297 args[1] = (UInt)readfds;
298 args[2] = (UInt)writefds;
299 args[3] = (UInt)exceptfds;
300 args[4] = (UInt)timeout;
jsgf855d93d2003-10-13 22:26:55 +0000301 res = VG_(do_syscall)(__NR_select, (UInt)(&(args[0])) );
sewardj2e93c502002-04-12 11:12:52 +0000302 return VG_(is_kerror)(res) ? -1 : res;
sewardj2e93c502002-04-12 11:12:52 +0000303}
304
jsgf855d93d2003-10-13 22:26:55 +0000305Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
306{
307 Int res = VG_(do_syscall)(__NR_poll, ufds, nfds, timeout);
308
309 return res;
310}
311
sewardj5f07b662002-04-23 16:52:51 +0000312/* Returns -1 on error, 0 if ok, 1 if interrupted. */
sewardj2e93c502002-04-12 11:12:52 +0000313Int VG_(nanosleep)( const struct vki_timespec *req,
314 struct vki_timespec *rem )
315{
316 Int res;
jsgf855d93d2003-10-13 22:26:55 +0000317 res = VG_(do_syscall)(__NR_nanosleep, (UInt)req, (UInt)rem);
sewardj2e93c502002-04-12 11:12:52 +0000318 if (res == -VKI_EINVAL) return -1;
sewardj5f07b662002-04-23 16:52:51 +0000319 if (res == -VKI_EINTR) return 1;
sewardj2e93c502002-04-12 11:12:52 +0000320 return 0;
321}
322
sewardjb3586202002-05-09 17:38:13 +0000323void* VG_(brk) ( void* end_data_segment )
324{
325 Int res;
jsgf855d93d2003-10-13 22:26:55 +0000326 res = VG_(do_syscall)(__NR_brk, (UInt)end_data_segment);
sewardjb3586202002-05-09 17:38:13 +0000327 return (void*)( VG_(is_kerror)(res) ? -1 : res );
328}
329
sewardj2e93c502002-04-12 11:12:52 +0000330
sewardjde4a1d02002-03-22 01:27:54 +0000331/* ---------------------------------------------------------------------
332 printf implementation. The key function, vg_vprintf(), emits chars
333 into a caller-supplied function. Distantly derived from:
334
335 vprintf replacement for Checker.
336 Copyright 1993, 1994, 1995 Tristan Gingold
337 Written September 1993 Tristan Gingold
338 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
339
340 (Checker itself was GPL'd.)
341 ------------------------------------------------------------------ */
342
343
344/* Some flags. */
345#define VG_MSG_SIGNED 1 /* The value is signed. */
346#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
347#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
sewardj78e3cd92002-10-22 04:45:48 +0000348#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
njn607adfc2003-09-30 14:15:44 +0000349#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
sewardjde4a1d02002-03-22 01:27:54 +0000350
351/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000352static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000353myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
354 Bool capitalise )
355{
356# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000357 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000358 Int i, extra;
359 Int len = VG_(strlen)(str);
360
361 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000362 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000363 for (i = 0; i < len; i++)
364 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000365 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000366 }
367
368 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000369 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000370 for (i = 0; i < width; i++)
371 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000372 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000373 }
374
375 extra = width - len;
376 if (flags & VG_MSG_LJUSTIFY) {
sewardj78e3cd92002-10-22 04:45:48 +0000377 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000378 for (i = 0; i < extra; i++)
379 send(' ');
380 }
sewardj78e3cd92002-10-22 04:45:48 +0000381 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000382 for (i = 0; i < len; i++)
383 send(MAYBE_TOUPPER(str[i]));
384 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000385 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000386 for (i = 0; i < extra; i++)
387 send(' ');
388 }
389
390# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000391
392 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000393}
394
395/* Write P into the buffer according to these args:
396 * If SIGN is true, p is a signed.
397 * BASE is the base.
398 * If WITH_ZERO is true, '0' must be added.
399 * WIDTH is the width of the field.
400 */
sewardj78e3cd92002-10-22 04:45:48 +0000401static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000402myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
403{
404 Char buf[40];
405 Int ind = 0;
njn607adfc2003-09-30 14:15:44 +0000406 Int i, nc = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000407 Bool neg = False;
408 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000409 UInt ret = 0;
410
sewardjde4a1d02002-03-22 01:27:54 +0000411 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000412 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000413
414 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
415 p = - (Long)p;
416 neg = True;
417 }
418
419 if (p == 0)
420 buf[ind++] = '0';
421 else {
422 while (p > 0) {
njn607adfc2003-09-30 14:15:44 +0000423 if (flags & VG_MSG_COMMA && 10 == base &&
424 0 == (ind-nc) % 3 && 0 != ind)
425 {
426 buf[ind++] = ',';
427 nc++;
428 }
sewardjde4a1d02002-03-22 01:27:54 +0000429 buf[ind++] = digits[p % base];
430 p /= base;
njn607adfc2003-09-30 14:15:44 +0000431 }
sewardjde4a1d02002-03-22 01:27:54 +0000432 }
433
434 if (neg)
435 buf[ind++] = '-';
436
437 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
438 for(; ind < width; ind++) {
439 vg_assert(ind < 39);
440 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
441 }
442 }
443
444 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000445 ret += ind;
njn607adfc2003-09-30 14:15:44 +0000446 for (i = ind -1; i >= 0; i--) {
sewardjde4a1d02002-03-22 01:27:54 +0000447 send(buf[i]);
njn607adfc2003-09-30 14:15:44 +0000448 }
sewardjde4a1d02002-03-22 01:27:54 +0000449 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000450 for(; ind < width; ind++) {
451 ret++;
njn607adfc2003-09-30 14:15:44 +0000452 send(' '); // Never pad with zeroes on RHS -- changes the value!
sewardj78e3cd92002-10-22 04:45:48 +0000453 }
sewardjde4a1d02002-03-22 01:27:54 +0000454 }
sewardj78e3cd92002-10-22 04:45:48 +0000455 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000456}
457
458
459/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000460UInt
sewardjde4a1d02002-03-22 01:27:54 +0000461VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
462{
sewardj78e3cd92002-10-22 04:45:48 +0000463 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000464 int i;
465 int flags;
466 int width;
467 Bool is_long;
468
469 /* We assume that vargs has already been initialised by the
470 caller, using va_start, and that the caller will similarly
471 clean up with va_end.
472 */
473
474 for (i = 0; format[i] != 0; i++) {
475 if (format[i] != '%') {
476 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000477 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000478 continue;
479 }
480 i++;
481 /* A '%' has been found. Ignore a trailing %. */
482 if (format[i] == 0)
483 break;
484 if (format[i] == '%') {
485 /* `%%' is replaced by `%'. */
486 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000487 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000488 continue;
489 }
490 flags = 0;
491 is_long = False;
492 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000493 if (format[i] == '(') {
494 flags |= VG_MSG_PAREN;
495 i++;
496 }
njn607adfc2003-09-30 14:15:44 +0000497 /* If ',' follows '%', commas will be inserted. */
498 if (format[i] == ',') {
499 flags |= VG_MSG_COMMA;
500 i++;
501 }
sewardjde4a1d02002-03-22 01:27:54 +0000502 /* If '-' follows '%', justify on the left. */
503 if (format[i] == '-') {
504 flags |= VG_MSG_LJUSTIFY;
505 i++;
506 }
507 /* If '0' follows '%', pads will be inserted. */
508 if (format[i] == '0') {
509 flags |= VG_MSG_ZJUSTIFY;
510 i++;
511 }
512 /* Compute the field length. */
513 while (format[i] >= '0' && format[i] <= '9') {
514 width *= 10;
515 width += format[i++] - '0';
516 }
517 while (format[i] == 'l') {
518 i++;
519 is_long = True;
520 }
521
522 switch (format[i]) {
523 case 'd': /* %d */
524 flags |= VG_MSG_SIGNED;
525 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000526 ret += myvprintf_int64(send, flags, 10, width,
527 (ULong)(va_arg (vargs, Long)));
sewardjde4a1d02002-03-22 01:27:54 +0000528 else
sewardj78e3cd92002-10-22 04:45:48 +0000529 ret += myvprintf_int64(send, flags, 10, width,
530 (ULong)(va_arg (vargs, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000531 break;
532 case 'u': /* %u */
533 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000534 ret += myvprintf_int64(send, flags, 10, width,
535 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000536 else
sewardj78e3cd92002-10-22 04:45:48 +0000537 ret += myvprintf_int64(send, flags, 10, width,
538 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000539 break;
540 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000541 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000542 send('0');
543 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000544 ret += myvprintf_int64(send, flags, 16, width,
545 (ULong)((UInt)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000546 break;
547 case 'x': /* %x */
548 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000549 ret += myvprintf_int64(send, flags, 16, width,
550 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000551 else
sewardj78e3cd92002-10-22 04:45:48 +0000552 ret += myvprintf_int64(send, flags, 16, width,
553 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000554 break;
555 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000556 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000557 send(va_arg (vargs, int));
558 break;
559 case 's': case 'S': { /* %s */
560 char *str = va_arg (vargs, char *);
561 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000562 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000563 break;
sewardj78e3cd92002-10-22 04:45:48 +0000564 }
565 case 'y': { /* %y - print symbol */
566 Char buf[100];
567 Char *cp = buf;
568 Addr a = va_arg(vargs, Addr);
569
570 if (flags & VG_MSG_PAREN)
571 *cp++ = '(';
sewardj6e008cb2002-12-15 13:11:39 +0000572 if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
sewardj78e3cd92002-10-22 04:45:48 +0000573 if (flags & VG_MSG_PAREN) {
574 cp += VG_(strlen)(cp);
575 *cp++ = ')';
576 *cp = '\0';
577 }
578 ret += myvprintf_str(send, flags, width, buf, 0);
579 }
580
581 break;
582 }
sewardjde4a1d02002-03-22 01:27:54 +0000583 default:
584 break;
585 }
586 }
sewardj78e3cd92002-10-22 04:45:48 +0000587 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000588}
589
590
591/* A general replacement for printf(). Note that only low-level
592 debugging info should be sent via here. The official route is to
593 to use vg_message(). This interface is deprecated.
594*/
595static char myprintf_buf[100];
596static int n_myprintf_buf;
597
598static void add_to_myprintf_buf ( Char c )
599{
600 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
sewardj73cf3bc2002-11-03 03:20:15 +0000601 if (VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000602 VG_(send_bytes_to_logging_sink)(
603 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000604 }
sewardjde4a1d02002-03-22 01:27:54 +0000605 n_myprintf_buf = 0;
606 myprintf_buf[n_myprintf_buf] = 0;
607 }
608 myprintf_buf[n_myprintf_buf++] = c;
609 myprintf_buf[n_myprintf_buf] = 0;
610}
611
sewardj78e3cd92002-10-22 04:45:48 +0000612UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000613{
sewardj78e3cd92002-10-22 04:45:48 +0000614 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000615 va_list vargs;
616 va_start(vargs,format);
617
618 n_myprintf_buf = 0;
619 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000620 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000621
sewardj73cf3bc2002-11-03 03:20:15 +0000622 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000623 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000624 }
sewardjde4a1d02002-03-22 01:27:54 +0000625
626 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000627
628 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000629}
630
631
632/* A general replacement for sprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000633UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000634{
sewardj05bcdcb2003-05-18 10:05:38 +0000635 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000636 va_list vargs;
sewardj1771e172002-11-13 22:06:35 +0000637 Char *ptr = buf;
638 static void add_to_vg_sprintf_buf ( Char c )
639 {
640 *ptr++ = c;
641 }
642
sewardjde4a1d02002-03-22 01:27:54 +0000643 va_start(vargs,format);
644
sewardj78e3cd92002-10-22 04:45:48 +0000645 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000646 add_to_vg_sprintf_buf(0);
647
648 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000649
650 vg_assert(VG_(strlen)(buf) == ret);
651 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000652}
653
654
655/* ---------------------------------------------------------------------
656 Misc str* functions.
657 ------------------------------------------------------------------ */
658
659Bool VG_(isspace) ( Char c )
660{
661 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
662}
663
njn7cf0bd32002-06-08 13:36:03 +0000664Bool VG_(isdigit) ( Char c )
665{
666 return (c >= '0' && c <= '9');
667}
sewardjde4a1d02002-03-22 01:27:54 +0000668
669Int VG_(strlen) ( const Char* str )
670{
671 Int i = 0;
672 while (str[i] != 0) i++;
673 return i;
674}
675
676
677Long VG_(atoll) ( Char* str )
678{
679 Bool neg = False;
680 Long n = 0;
681 if (*str == '-') { str++; neg = True; };
682 while (*str >= '0' && *str <= '9') {
683 n = 10*n + (Long)(*str - '0');
684 str++;
685 }
686 if (neg) n = -n;
687 return n;
688}
689
690
njn25e49d8e72002-09-23 09:36:25 +0000691Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000692{
693 Bool neg = False;
694 Long n = 0;
695 if (*str == '-') { str++; neg = True; };
696 while (True) {
697 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000698 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000699 }
700 else
njn25e49d8e72002-09-23 09:36:25 +0000701 if (*str >= 'A' && *str <= 'F') {
702 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000703 }
704 else
njn25e49d8e72002-09-23 09:36:25 +0000705 if (*str >= 'a' && *str <= 'f') {
706 n = 16*n + (Long)((*str - 'a') + 10);
707 }
708 else {
709 break;
710 }
711 str++;
712 }
713 if (neg) n = -n;
714 return n;
715}
716
717Long VG_(atoll36) ( UInt base, Char* str )
718{
719 Bool neg = False;
720 Long n = 0;
721 vg_assert(base >= 2 && base <= 36);
722 if (*str == '-') { str++; neg = True; };
723 while (True) {
sewardj05bcdcb2003-05-18 10:05:38 +0000724 if (*str >= '0'
725 && *str <= (Char)('9' - (10 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000726 n = base*n + (Long)(*str - '0');
727 }
728 else
sewardj05bcdcb2003-05-18 10:05:38 +0000729 if (base > 10 && *str >= 'A'
730 && *str <= (Char)('Z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000731 n = base*n + (Long)((*str - 'A') + 10);
732 }
733 else
sewardj05bcdcb2003-05-18 10:05:38 +0000734 if (base > 10 && *str >= 'a'
735 && *str <= (Char)('z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000736 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000737 }
738 else {
739 break;
740 }
741 str++;
742 }
743 if (neg) n = -n;
744 return n;
745}
746
747
sewardjde4a1d02002-03-22 01:27:54 +0000748Char* VG_(strcat) ( Char* dest, const Char* src )
749{
750 Char* dest_orig = dest;
751 while (*dest) dest++;
752 while (*src) *dest++ = *src++;
753 *dest = 0;
754 return dest_orig;
755}
756
757
758Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
759{
760 Char* dest_orig = dest;
761 while (*dest) dest++;
762 while (*src && n > 0) { *dest++ = *src++; n--; }
763 *dest = 0;
764 return dest_orig;
765}
766
767
768Char* VG_(strpbrk) ( const Char* s, const Char* accept )
769{
770 const Char* a;
771 while (*s) {
772 a = accept;
773 while (*a)
774 if (*a++ == *s)
775 return (Char *) s;
776 s++;
777 }
778 return NULL;
779}
780
781
782Char* VG_(strcpy) ( Char* dest, const Char* src )
783{
784 Char* dest_orig = dest;
785 while (*src) *dest++ = *src++;
786 *dest = 0;
787 return dest_orig;
788}
789
790
791/* Copy bytes, not overrunning the end of dest and always ensuring
792 zero termination. */
793void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
794{
795 Int i;
796 vg_assert(ndest > 0);
797 i = 0;
798 dest[i] = 0;
799 while (True) {
800 if (src[i] == 0) return;
801 if (i >= ndest-1) return;
802 dest[i] = src[i];
803 i++;
804 dest[i] = 0;
805 }
806}
807
808
njn25e49d8e72002-09-23 09:36:25 +0000809Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000810{
njn25e49d8e72002-09-23 09:36:25 +0000811 Int i = 0;
812 while (True) {
813 if (i >= ndest) return dest; /* reached limit */
814 dest[i] = src[i];
815 if (src[i++] == 0) {
816 /* reached NUL; pad rest with zeroes as required */
817 while (i < ndest) dest[i++] = 0;
818 return dest;
819 }
820 }
sewardjde4a1d02002-03-22 01:27:54 +0000821}
822
823
824Int VG_(strcmp) ( const Char* s1, const Char* s2 )
825{
826 while (True) {
827 if (*s1 == 0 && *s2 == 0) return 0;
828 if (*s1 == 0) return -1;
829 if (*s2 == 0) return 1;
830
831 if (*(UChar*)s1 < *(UChar*)s2) return -1;
832 if (*(UChar*)s1 > *(UChar*)s2) return 1;
833
834 s1++; s2++;
835 }
836}
837
838
839Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
840{
841 while (True) {
842 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
843 if (VG_(isspace)(*s1)) return -1;
844 if (VG_(isspace)(*s2)) return 1;
845
846 if (*(UChar*)s1 < *(UChar*)s2) return -1;
847 if (*(UChar*)s1 > *(UChar*)s2) return 1;
848
849 s1++; s2++;
850 }
851}
852
853
854Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
855{
856 Int n = 0;
857 while (True) {
858 if (n >= nmax) return 0;
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++; n++;
867 }
868}
869
870
871Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
872{
873 Int n = 0;
874 while (True) {
875 if (n >= nmax) return 0;
876 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
877 if (VG_(isspace)(*s1)) return -1;
878 if (VG_(isspace)(*s2)) return 1;
879
880 if (*(UChar*)s1 < *(UChar*)s2) return -1;
881 if (*(UChar*)s1 > *(UChar*)s2) return 1;
882
883 s1++; s2++; n++;
884 }
885}
886
887
888Char* VG_(strstr) ( const Char* haystack, Char* needle )
889{
sewardj3984b852002-05-12 03:00:17 +0000890 Int n;
891 if (haystack == NULL)
892 return NULL;
893 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000894 while (True) {
895 if (haystack[0] == 0)
896 return NULL;
897 if (VG_(strncmp)(haystack, needle, n) == 0)
898 return (Char*)haystack;
899 haystack++;
900 }
901}
902
903
904Char* VG_(strchr) ( const Char* s, Char c )
905{
906 while (True) {
907 if (*s == c) return (Char*)s;
908 if (*s == 0) return NULL;
909 s++;
910 }
911}
912
913
sewardj7ab2aca2002-10-20 19:40:32 +0000914void* VG_(memcpy) ( void *dest, const void *src, Int sz )
915{
916 const Char *s = (const Char *)src;
917 Char *d = (Char *)dest;
918 vg_assert(sz >= 0);
919
920 while (sz--)
921 *d++ = *s++;
922
923 return dest;
924}
925
926
927void* VG_(memset) ( void *dest, Int c, Int sz )
928{
929 Char *d = (Char *)dest;
930 vg_assert(sz >= 0);
931
932 while (sz--)
933 *d++ = c;
934
935 return dest;
936}
937
njn6d68e792003-02-24 10:49:08 +0000938Int VG_(memcmp) ( const void* s1, const void* s2, Int n )
939{
940 Int res;
njnfa4690b2003-02-24 21:43:05 +0000941 UChar a0;
942 UChar b0;
njn6d68e792003-02-24 10:49:08 +0000943 vg_assert(n >= 0);
944
945 while (n != 0) {
njnfa4690b2003-02-24 21:43:05 +0000946 a0 = ((UChar *) s1)[0];
947 b0 = ((UChar *) s2)[0];
njn6d68e792003-02-24 10:49:08 +0000948 s1 += 1;
949 s2 += 1;
950 res = a0 - b0;
951 if (res != 0)
952 return res;
953 n -= 1;
954 }
955 return 0;
956}
sewardj7ab2aca2002-10-20 19:40:32 +0000957
sewardjde4a1d02002-03-22 01:27:54 +0000958Char VG_(toupper) ( Char c )
959{
960 if (c >= 'a' && c <= 'z')
961 return c + ('A' - 'a');
962 else
963 return c;
964}
965
966
njn25e49d8e72002-09-23 09:36:25 +0000967/* Inline just for the wrapper VG_(strdup) below */
968__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +0000969{
njn25e49d8e72002-09-23 09:36:25 +0000970 Int i;
fitzhardingea7728472003-12-16 01:48:38 +0000971 Int len;
972 Char* res;
973
974 if (s == NULL)
975 return NULL;
976
977 len = VG_(strlen)(s) + 1;
978 res = VG_(arena_malloc) (aid, len);
979
njn25e49d8e72002-09-23 09:36:25 +0000980 for (i = 0; i < len; i++)
981 res[i] = s[i];
982 return res;
sewardjde4a1d02002-03-22 01:27:54 +0000983}
984
njn25e49d8e72002-09-23 09:36:25 +0000985/* Wrapper to avoid exposing skins to ArenaId's */
986Char* VG_(strdup) ( const Char* s )
987{
988 return VG_(arena_strdup) ( VG_AR_SKIN, s );
989}
sewardjde4a1d02002-03-22 01:27:54 +0000990
991/* ---------------------------------------------------------------------
992 A simple string matching routine, purloined from Hugs98.
993 `*' matches any sequence of zero or more characters
994 `?' matches any single character exactly
995 `\c' matches the character c only (ignoring special chars)
996 c matches the character c only
997 ------------------------------------------------------------------ */
998
999/* Keep track of recursion depth. */
1000static Int recDepth;
1001
njn4ba5a792002-09-30 10:23:54 +00001002static Bool string_match_wrk ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001003{
sewardje54b69d2003-07-06 01:14:42 +00001004 vg_assert(recDepth >= 0 && recDepth < 500);
sewardjde4a1d02002-03-22 01:27:54 +00001005 recDepth++;
1006 for (;;) {
1007 switch (*pat) {
1008 case '\0' : return (*str=='\0');
1009 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001010 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001011 recDepth--;
1012 return True;
1013 }
1014 } while (*str++);
1015 recDepth--;
1016 return False;
1017 case '?' : if (*str++=='\0') {
1018 recDepth--;
1019 return False;
1020 }
1021 pat++;
1022 break;
1023 case '\\' : if (*++pat == '\0') {
1024 recDepth--;
1025 return False; /* spurious trailing \ in pattern */
1026 }
1027 /* falls through to ... */
1028 default : if (*pat++ != *str++) {
1029 recDepth--;
1030 return False;
1031 }
1032 break;
1033 }
1034 }
1035}
1036
njn4ba5a792002-09-30 10:23:54 +00001037Bool VG_(string_match) ( Char* pat, Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001038{
1039 Bool b;
1040 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001041 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001042 /*
1043 VG_(printf)("%s %s %s\n",
1044 b?"TRUE ":"FALSE", pat, str);
1045 */
1046 return b;
1047}
1048
1049
1050/* ---------------------------------------------------------------------
1051 Assertery.
1052 ------------------------------------------------------------------ */
1053
jsgf855d93d2003-10-13 22:26:55 +00001054/* Fake up an ExeContext which is of our actual real CPU state, so we
1055 can print a stack trace. This isn't terribly useful in the case
1056 where we were killed by a signal, since we just get a backtrace
1057 into the signal handler. Also, it could be somewhat risky if we
1058 actully got the panic/exception within the execontext/stack
1059 dump/symtab code. But it's better than nothing. */
1060static inline ExeContext *get_real_execontext(Addr ret)
1061{
1062 ExeContext *ec;
fitzhardingea09a1b52003-11-07 23:09:48 +00001063 Addr esp, ebp;
jsgf855d93d2003-10-13 22:26:55 +00001064 Addr stacktop;
jsgf855d93d2003-10-13 22:26:55 +00001065
fitzhardingea09a1b52003-11-07 23:09:48 +00001066 asm("movl %%ebp, %0; movl %%esp, %1" : "=r" (ebp), "=r" (esp));
jsgf855d93d2003-10-13 22:26:55 +00001067 stacktop = (Addr)&VG_(stack)[VG_STACK_SIZE_W];
1068 if (esp >= (Addr)&VG_(sigstack)[0] && esp < (Addr)&VG_(sigstack)[VG_STACK_SIZE_W])
1069 stacktop = (Addr)&VG_(sigstack)[VG_STACK_SIZE_W];
1070
1071 ec = VG_(get_ExeContext2)(ret, ebp, esp, stacktop);
1072
1073 return ec;
1074}
1075
njne427a662002-10-02 11:08:25 +00001076__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001077static void report_and_quit ( const Char* report )
njne427a662002-10-02 11:08:25 +00001078{
jsgf855d93d2003-10-13 22:26:55 +00001079 ExeContext *ec = get_real_execontext((Addr)__builtin_return_address(0));
1080 VG_(pp_ExeContext)(ec);
1081
njne427a662002-10-02 11:08:25 +00001082 VG_(pp_sched_status)();
sewardj366ee1e2003-04-26 22:36:42 +00001083 VG_(printf)("\n");
1084 VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
1085 VG_(printf)("It contains workarounds to several common problems.\n");
1086 VG_(printf)("\n");
1087 VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
1088 report);
1089 VG_(printf)("In the bug report, send all the above text, the valgrind\n");
sewardj96330bd2003-04-27 23:46:21 +00001090 VG_(printf)("version, and what Linux distro you are using. Thanks.\n\n");
njne427a662002-10-02 11:08:25 +00001091 VG_(shutdown_logging)();
1092 VG_(exit)(1);
1093}
1094
1095__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001096static void assert_fail ( const Char* expr, const Char* name, const Char* report,
1097 const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001098{
sewardj018f7622002-05-15 21:13:39 +00001099 static Bool entered = False;
1100 if (entered)
1101 VG_(exit)(2);
1102 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001103 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001104 name, file, line, fn, expr );
1105 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001106}
1107
daywalker3222e0a2003-09-18 01:39:50 +00001108void VG_(skin_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001109{
njnd04b7c62002-10-03 14:05:52 +00001110 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001111 file, line, fn);
1112}
1113
daywalker3222e0a2003-09-18 01:39:50 +00001114void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
njne427a662002-10-02 11:08:25 +00001115{
nethercote421281e2003-11-20 16:20:55 +00001116 assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn);
njne427a662002-10-02 11:08:25 +00001117}
1118
1119__attribute__ ((noreturn))
1120static void panic ( Char* name, Char* report, Char* str )
1121{
1122 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001123 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
njne427a662002-10-02 11:08:25 +00001124 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001125}
1126
njne427a662002-10-02 11:08:25 +00001127void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001128{
nethercote421281e2003-11-20 16:20:55 +00001129 panic("valgrind", VG_BUGS_TO, str);
njn25e49d8e72002-09-23 09:36:25 +00001130}
1131
njne427a662002-10-02 11:08:25 +00001132void VG_(skin_panic) ( Char* str )
1133{
njnd04b7c62002-10-03 14:05:52 +00001134 panic(VG_(details).name, VG_(details).bug_reports_to, str);
njne427a662002-10-02 11:08:25 +00001135}
sewardjde4a1d02002-03-22 01:27:54 +00001136
njn13f02932003-04-30 20:23:58 +00001137
sewardjde4a1d02002-03-22 01:27:54 +00001138/* ---------------------------------------------------------------------
1139 Primitive support for reading files.
1140 ------------------------------------------------------------------ */
1141
jsgf855d93d2003-10-13 22:26:55 +00001142static inline Bool fd_exists(Int fd)
1143{
1144 struct vki_stat st;
1145
1146 return VG_(fstat)(fd, &st) == 0;
1147}
1148
1149/* Move an fd into the Valgrind-safe range */
1150Int VG_(safe_fd)(Int oldfd)
1151{
1152 Int newfd;
1153
1154 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_MAX_FD+1);
1155 if (newfd != -1)
1156 VG_(close)(oldfd);
1157
1158 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
1159
1160 vg_assert(newfd > VG_MAX_FD);
1161 return newfd;
1162}
1163
1164
1165
sewardjde4a1d02002-03-22 01:27:54 +00001166/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001167Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1168{
sewardjde4a1d02002-03-22 01:27:54 +00001169 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001170
njn25e49d8e72002-09-23 09:36:25 +00001171 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001172 /* This gets a segmentation fault if pathname isn't a valid file.
1173 I don't know why. It seems like the call to open is getting
1174 intercepted and messed with by glibc ... */
1175 /* fd = open( pathname, O_RDONLY ); */
1176 /* ... so we go direct to the horse's mouth, which seems to work
1177 ok: */
jsgf855d93d2003-10-13 22:26:55 +00001178 fd = VG_(do_syscall)(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001179 /* VG_(printf)("result = %d\n", fd); */
jsgff3c3f1a2003-10-14 22:13:28 +00001180 /* return -ve error code */
njn4f9c9342002-04-29 16:03:24 +00001181 return fd;
1182}
sewardjde4a1d02002-03-22 01:27:54 +00001183
jsgf855d93d2003-10-13 22:26:55 +00001184Int VG_(pipe) ( Int fd[2] )
1185{
1186 Int ret = VG_(do_syscall)(__NR_pipe, fd);
1187 return VG_(is_kerror)(ret) ? -1 : 0;
1188}
1189
sewardjde4a1d02002-03-22 01:27:54 +00001190void VG_(close) ( Int fd )
1191{
jsgf855d93d2003-10-13 22:26:55 +00001192 VG_(do_syscall)(__NR_close, fd);
sewardjde4a1d02002-03-22 01:27:54 +00001193}
1194
1195
1196Int VG_(read) ( Int fd, void* buf, Int count)
1197{
1198 Int res;
1199 /* res = read( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001200 res = VG_(do_syscall)(__NR_read, fd, (UInt)buf, count);
1201 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001202 return res;
1203}
1204
jsgf855d93d2003-10-13 22:26:55 +00001205Int VG_(write) ( Int fd, const void* buf, Int count)
sewardjde4a1d02002-03-22 01:27:54 +00001206{
1207 Int res;
1208 /* res = write( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001209 res = VG_(do_syscall)(__NR_write, fd, (UInt)buf, count);
1210 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001211 return res;
1212}
1213
rjwalshf5f536f2003-11-17 17:45:00 +00001214Int VG_(lseek) ( Int fd, Long offset, Int whence)
1215{
1216 Int res;
1217 /* res = lseek( fd, offset, whence ); */
1218 res = VG_(do_syscall)(__NR_lseek, fd, (UInt)offset, whence);
1219 if (VG_(is_kerror)(res)) res = -1;
1220 return res;
1221}
1222
sewardjb3586202002-05-09 17:38:13 +00001223Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1224{
1225 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001226 res = VG_(do_syscall)(__NR_stat, (UInt)file_name, (UInt)buf);
fitzhardingee1c06d82003-10-30 07:21:44 +00001227 return res; /* return -ve error */
njn41557122002-10-14 09:25:37 +00001228}
1229
jsgf855d93d2003-10-13 22:26:55 +00001230Int VG_(fstat) ( Int fd, struct vki_stat* buf )
1231{
1232 Int res;
1233 res = VG_(do_syscall)(__NR_fstat, (UInt)fd, (UInt)buf);
1234 return VG_(is_kerror)(res) ? (-1) : 0;
1235}
1236
1237Int VG_(dup2) ( Int oldfd, Int newfd )
1238{
1239 Int res;
1240 res = VG_(do_syscall)(__NR_dup2, (UInt)oldfd, (UInt)newfd);
1241 return VG_(is_kerror)(res) ? (-1) : res;
1242}
1243
njn41557122002-10-14 09:25:37 +00001244Int VG_(rename) ( Char* old_name, Char* new_name )
1245{
1246 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001247 res = VG_(do_syscall)(__NR_rename, (UInt)old_name, (UInt)new_name);
njn41557122002-10-14 09:25:37 +00001248 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001249}
1250
njn4aca2d22002-10-04 10:29:38 +00001251Int VG_(unlink) ( Char* file_name )
1252{
1253 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001254 res = VG_(do_syscall)(__NR_unlink, (UInt)file_name);
njn41557122002-10-14 09:25:37 +00001255 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001256}
1257
njn13f02932003-04-30 20:23:58 +00001258/* Nb: we do not allow the Linux extension which malloc()s memory for the
1259 buffer if buf==NULL, because we don't want Linux calling malloc() */
1260Char* VG_(getcwd) ( Char* buf, Int size )
1261{
1262 Int res;
1263 vg_assert(buf != NULL);
jsgf855d93d2003-10-13 22:26:55 +00001264 res = VG_(do_syscall)(__NR_getcwd, (UInt)buf, (UInt)size);
njn13f02932003-04-30 20:23:58 +00001265 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1266}
1267
njn99ccf082003-09-30 13:51:23 +00001268/* Alternative version that does allocate the memory. Easier to use. */
1269Bool VG_(getcwd_alloc) ( Char** out )
1270{
1271 UInt size = 4;
1272
1273 *out = NULL;
1274 while (True) {
1275 *out = VG_(malloc)(size);
1276 if (NULL == VG_(getcwd)(*out, size)) {
1277 VG_(free)(*out);
1278 if (size > 65535)
1279 return False;
1280 size *= 2;
1281 } else {
1282 return True;
1283 }
1284 }
1285}
1286
njn13f02932003-04-30 20:23:58 +00001287
1288/* ---------------------------------------------------------------------
1289 Misc functions looking for a proper home.
1290 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001291
1292/* We do getenv without libc's help by snooping around in
njn25e49d8e72002-09-23 09:36:25 +00001293 VG_(client_envp) as determined at startup time. */
sewardjde4a1d02002-03-22 01:27:54 +00001294Char* VG_(getenv) ( Char* varname )
1295{
1296 Int i, n;
1297 n = VG_(strlen)(varname);
1298 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1299 Char* s = VG_(client_envp)[i];
1300 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1301 return & s[n+1];
1302 }
1303 }
1304 return NULL;
1305}
1306
sewardj4cf05692002-10-27 20:28:29 +00001307
rjwalshf5f536f2003-11-17 17:45:00 +00001308/* Support for getrlimit. */
1309Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
1310{
1311 Int res;
1312 /* res = getrlimit( resource, rlim ); */
1313 res = VG_(do_syscall)(__NR_getrlimit, (UInt)resource, (UInt)rlim);
1314 if(VG_(is_kerror)(res)) res = -1;
1315 return res;
1316}
1317
1318
1319/* Support for getdents. */
1320Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
1321{
1322 Int res;
1323 /* res = getdents( fd, dirp, count ); */
1324 res = VG_(do_syscall)(__NR_getdents, fd, (UInt)dirp, count);
1325 if (VG_(is_kerror)(res)) res = -1;
1326 return res;
1327}
1328
1329/* Support for a readlink. */
1330Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
1331{
1332 Int res;
1333 /* res = readlink( path, buf, bufsiz ); */
1334 res = VG_(do_syscall)(__NR_readlink, (UInt)path, (UInt)buf, bufsiz);
1335 if (VG_(is_kerror)(res)) res = -1;
1336 return res;
1337}
1338
sewardjde4a1d02002-03-22 01:27:54 +00001339/* You'd be amazed how many places need to know the current pid. */
1340Int VG_(getpid) ( void )
1341{
1342 Int res;
1343 /* res = getpid(); */
jsgf855d93d2003-10-13 22:26:55 +00001344 res = VG_(do_syscall)(__NR_getpid);
1345 return res;
1346}
1347
1348Int VG_(getpgrp) ( void )
1349{
1350 Int res;
1351 /* res = getpgid(); */
1352 res = VG_(do_syscall)(__NR_getpgrp);
sewardjde4a1d02002-03-22 01:27:54 +00001353 return res;
1354}
1355
sewardj4cf05692002-10-27 20:28:29 +00001356Int VG_(getppid) ( void )
1357{
1358 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001359 res = VG_(do_syscall)(__NR_getppid);
sewardj4cf05692002-10-27 20:28:29 +00001360 return res;
1361}
1362
jsgf855d93d2003-10-13 22:26:55 +00001363Int VG_(setpgid) ( Int pid, Int pgrp )
1364{
1365 return VG_(do_syscall)(__NR_setpgid, pid, pgrp);
1366}
sewardj4cf05692002-10-27 20:28:29 +00001367
sewardje6a25242002-04-21 22:03:07 +00001368/* Return -1 if error, else 0. NOTE does not indicate return code of
1369 child! */
1370Int VG_(system) ( Char* cmd )
1371{
1372 Int pid, res;
1373 void* environ[1] = { NULL };
1374 if (cmd == NULL)
1375 return 1;
jsgf855d93d2003-10-13 22:26:55 +00001376 pid = VG_(do_syscall)(__NR_fork);
sewardje6a25242002-04-21 22:03:07 +00001377 if (VG_(is_kerror)(pid))
1378 return -1;
1379 if (pid == 0) {
1380 /* child */
1381 Char* argv[4];
1382 argv[0] = "/bin/sh";
1383 argv[1] = "-c";
1384 argv[2] = cmd;
1385 argv[3] = 0;
jsgf855d93d2003-10-13 22:26:55 +00001386 (void)VG_(do_syscall)(__NR_execve,
1387 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
sewardje6a25242002-04-21 22:03:07 +00001388 /* If we're still alive here, execve failed. */
1389 return -1;
1390 } else {
1391 /* parent */
jsgf855d93d2003-10-13 22:26:55 +00001392 res = VG_(do_syscall)(__NR_waitpid, pid, (UInt)NULL, 0);
sewardje6a25242002-04-21 22:03:07 +00001393 if (VG_(is_kerror)(res)) {
1394 return -1;
1395 } else {
1396 return 0;
1397 }
1398 }
1399}
1400
1401
sewardjde4a1d02002-03-22 01:27:54 +00001402/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001403 Support for a millisecond-granularity counter using RDTSC.
1404 ------------------------------------------------------------------ */
1405
1406static __inline__ ULong do_rdtsc_insn ( void )
1407{
1408 ULong x;
1409 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1410 return x;
1411}
1412
1413/* 0 = pre-calibration, 1 = calibration, 2 = running */
1414static Int rdtsc_calibration_state = 0;
1415static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1416
1417static struct vki_timeval rdtsc_cal_start_timeval;
1418static struct vki_timeval rdtsc_cal_end_timeval;
1419
1420static ULong rdtsc_cal_start_raw;
1421static ULong rdtsc_cal_end_raw;
1422
1423UInt VG_(read_millisecond_timer) ( void )
1424{
1425 ULong rdtsc_now;
njne7442cf2003-09-30 14:03:21 +00001426 // If called before rdtsc setup completed (eg. from SK_(pre_clo_init)())
1427 // just return 0.
1428 if (rdtsc_calibration_state < 2) return 0;
sewardj5f07b662002-04-23 16:52:51 +00001429 rdtsc_now = do_rdtsc_insn();
1430 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1431 rdtsc_now -= rdtsc_cal_end_raw;
1432 rdtsc_now /= rdtsc_ticks_per_millisecond;
1433 return (UInt)rdtsc_now;
1434}
1435
1436
1437void VG_(start_rdtsc_calibration) ( void )
1438{
1439 Int res;
1440 vg_assert(rdtsc_calibration_state == 0);
1441 rdtsc_calibration_state = 1;
1442 rdtsc_cal_start_raw = do_rdtsc_insn();
jsgf855d93d2003-10-13 22:26:55 +00001443 res = VG_(do_syscall)(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1444 (UInt)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001445 vg_assert(!VG_(is_kerror)(res));
1446}
1447
1448void VG_(end_rdtsc_calibration) ( void )
1449{
1450 Int res, loops;
1451 ULong cpu_clock_MHZ;
1452 ULong cal_clock_ticks;
1453 ULong cal_wallclock_microseconds;
1454 ULong wallclock_start_microseconds;
1455 ULong wallclock_end_microseconds;
1456 struct vki_timespec req;
1457 struct vki_timespec rem;
1458
1459 vg_assert(rdtsc_calibration_state == 1);
1460 rdtsc_calibration_state = 2;
1461
1462 /* Try and delay for 20 milliseconds, so that we can at least have
1463 some minimum level of accuracy. */
1464 req.tv_sec = 0;
1465 req.tv_nsec = 20 * 1000 * 1000;
1466 loops = 0;
1467 while (True) {
1468 res = VG_(nanosleep)(&req, &rem);
1469 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1470 if (res == 0)
1471 break;
1472 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1473 break;
1474 req = rem;
1475 loops++;
1476 if (loops > 100)
njne427a662002-10-02 11:08:25 +00001477 VG_(core_panic)("calibration nanosleep loop failed?!");
sewardj5f07b662002-04-23 16:52:51 +00001478 }
1479
1480 /* Now read both timers, and do the Math. */
1481 rdtsc_cal_end_raw = do_rdtsc_insn();
jsgf855d93d2003-10-13 22:26:55 +00001482 res = VG_(do_syscall)(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1483 (UInt)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001484
1485 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1486 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1487
1488 wallclock_start_microseconds
1489 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1490 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1491 wallclock_end_microseconds
1492 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1493 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1494 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1495 cal_wallclock_microseconds
1496 = wallclock_end_microseconds - wallclock_start_microseconds;
1497
1498 /* Since we just nanoslept for 20 ms ... */
1499 vg_assert(cal_wallclock_microseconds >= 20000);
1500
1501 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1502 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1503 ticks-per-millisecond value. */
1504 if (0)
1505 VG_(printf)("%lld ticks in %lld microseconds\n",
1506 cal_clock_ticks, cal_wallclock_microseconds );
1507
1508 rdtsc_ticks_per_millisecond
1509 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1510 cpu_clock_MHZ
1511 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1512 if (VG_(clo_verbosity) >= 1)
1513 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1514 (UInt)cpu_clock_MHZ);
sewardj09c55fd2002-06-13 11:37:41 +00001515 if (cpu_clock_MHZ < 50 || cpu_clock_MHZ > 10000)
njne427a662002-10-02 11:08:25 +00001516 VG_(core_panic)("end_rdtsc_calibration: "
sewardj09c55fd2002-06-13 11:37:41 +00001517 "estimated CPU MHz outside range 50 .. 10000");
sewardj5f07b662002-04-23 16:52:51 +00001518 /* Paranoia about division by zero later. */
1519 vg_assert(rdtsc_ticks_per_millisecond != 0);
1520 if (0)
1521 VG_(printf)("ticks per millisecond %llu\n",
1522 rdtsc_ticks_per_millisecond);
1523}
1524
1525
1526
1527/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001528 Primitive support for bagging memory via mmap.
1529 ------------------------------------------------------------------ */
1530
sewardje9047952002-06-05 20:28:33 +00001531void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001532{
1533 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001534 void* p;
1535 p = VG_(mmap)( 0, nBytes,
1536 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1537 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, -1, 0 );
sewardjde4a1d02002-03-22 01:27:54 +00001538 if (p != ((void*)(-1))) {
1539 tot_alloc += (UInt)nBytes;
1540 if (0)
sewardje9047952002-06-05 20:28:33 +00001541 VG_(printf)(
1542 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1543 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001544 return p;
1545 }
sewardj7c2020b2002-09-30 22:56:03 +00001546
njn25e49d8e72002-09-23 09:36:25 +00001547 VG_(printf)("\n");
daywalkerb1db1232003-09-26 00:26:07 +00001548 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %d bytes failed.\n",
1549 who, nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001550 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1551 tot_alloc);
1552 VG_(printf)("\n");
1553 VG_(printf)("This may mean that you have run out of swap space,\n");
1554 VG_(printf)("since running programs on valgrind increases their memory\n");
1555 VG_(printf)("usage at least 3 times. You might want to use 'top'\n");
1556 VG_(printf)("to determine whether you really have run out of swap.\n");
1557 VG_(printf)("If so, you may be able to work around it by adding a\n");
1558 VG_(printf)("temporary swap file -- this is easier than finding a\n");
1559 VG_(printf)("new swap partition. Go ask your sysadmin(s) [politely!]\n");
1560 VG_(printf)("\n");
1561 VG_(printf)("VG_(get_memory_from_mmap): out of memory! Fatal! Bye!\n");
1562 VG_(printf)("\n");
1563 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001564}
1565
njn25e49d8e72002-09-23 09:36:25 +00001566/* ---------------------------------------------------------------------
1567 Generally useful...
1568 ------------------------------------------------------------------ */
1569
1570Int VG_(log2) ( Int x )
1571{
1572 Int i;
1573 /* Any more than 32 and we overflow anyway... */
1574 for (i = 0; i < 32; i++) {
1575 if (1 << i == x) return i;
1576 }
1577 return -1;
1578}
1579
1580
njnd3b0c5f2003-09-30 14:43:54 +00001581// Generic shell sort. Like stdlib.h's qsort().
1582void VG_(ssort)( void* base, UInt nmemb, UInt size,
1583 Int (*compar)(void*, void*) )
1584{
1585 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1586 9841, 29524, 88573, 265720,
1587 797161, 2391484 };
1588 Int lo = 0;
1589 Int hi = nmemb-1;
1590 Int i, j, h, bigN, hp;
1591
1592 bigN = hi - lo + 1; if (bigN < 2) return;
1593 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1594 vg_assert(0 <= hp && hp < 14);
1595
1596 #define SORT \
1597 for ( ; hp >= 0; hp--) { \
1598 h = incs[hp]; \
njn92c54362003-10-15 14:00:35 +00001599 for (i = lo + h; i <= hi; i++) { \
njnd3b0c5f2003-09-30 14:43:54 +00001600 ASSIGN(v,0, a,i); \
1601 j = i; \
njn92c54362003-10-15 14:00:35 +00001602 while (COMPAR(a,(j-h), v,0) > 0) { \
njnd3b0c5f2003-09-30 14:43:54 +00001603 ASSIGN(a,j, a,(j-h)); \
1604 j = j - h; \
1605 if (j <= (lo + h - 1)) break; \
1606 } \
1607 ASSIGN(a,j, v,0); \
njnd3b0c5f2003-09-30 14:43:54 +00001608 } \
1609 }
1610
1611 // Specialised cases
1612 if (sizeof(UInt) == size) {
1613
1614 #define ASSIGN(dst, dsti, src, srci) \
1615 (dst)[(dsti)] = (src)[(srci)];
1616
1617 #define COMPAR(dst, dsti, src, srci) \
1618 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1619
1620 UInt* a = (UInt*)base;
1621 UInt v[1];
1622
1623 SORT;
1624
1625 } else if (sizeof(UShort) == size) {
1626 UShort* a = (UShort*)base;
1627 UShort v[1];
1628
1629 SORT;
1630
1631 } else if (sizeof(UChar) == size) {
1632 UChar* a = (UChar*)base;
1633 UChar v[1];
1634
1635 SORT;
1636
1637 #undef ASSIGN
1638 #undef COMPAR
1639
1640 // General case
1641 } else {
njn92c54362003-10-15 14:00:35 +00001642 char* a = base;
1643 char v[size]; // will be at least 'size' bytes
njnd3b0c5f2003-09-30 14:43:54 +00001644
1645 #define ASSIGN(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001646 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
njnd3b0c5f2003-09-30 14:43:54 +00001647
1648 #define COMPAR(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001649 compar( &dst[size*(dsti)], &src[size*(srci)] )
njnd3b0c5f2003-09-30 14:43:54 +00001650
1651 SORT;
1652
1653 #undef ASSIGN
1654 #undef COMPAR
1655 }
1656 #undef SORT
1657}
1658
sewardj73cf3bc2002-11-03 03:20:15 +00001659/* ---------------------------------------------------------------------
1660 Gruesome hackery for connecting to a logging server over the network.
1661 This is all very Linux-kernel specific.
1662 ------------------------------------------------------------------ */
1663
1664/* Various needed constants from the kernel iface (2.4),
1665 /usr/src/linux-2.4.9-31 */
1666
1667/* kernel, ./include/linux/net.h */
rjwalshf5f536f2003-11-17 17:45:00 +00001668#define SYS_SOCKET 1 /* sys_socket(2) */
1669#define SYS_CONNECT 3 /* sys_connect(2) */
1670#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
1671#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
1672#define SYS_SEND 9 /* sys_send(2) */
1673#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
sewardj73cf3bc2002-11-03 03:20:15 +00001674
1675typedef UInt __u32;
1676
1677/* Internet address. */
1678struct vki_in_addr {
1679 __u32 s_addr;
1680};
1681
1682/* kernel, include/linux/socket.h */
sewardj73cf3bc2002-11-03 03:20:15 +00001683#define AF_INET 2 /* Internet IP Protocol */
sewardj570f8902002-11-03 11:44:36 +00001684#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
sewardj73cf3bc2002-11-03 03:20:15 +00001685
1686/* kernel, ./include/asm-i386/socket.h */
1687#define SOCK_STREAM 1 /* stream (connection) socket */
1688
1689/* kernel, /usr/src/linux-2.4.9-31/linux/include/in.h */
1690/* Structure describing an Internet (IP) socket address. */
1691#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
1692struct vki_sockaddr_in {
1693 vki_sa_family_t sin_family; /* Address family */
1694 unsigned short int sin_port; /* Port number */
1695 struct vki_in_addr sin_addr; /* Internet address */
1696
1697 /* Pad to size of `struct sockaddr'. */
1698 unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
1699 sizeof(unsigned short int) -
1700 sizeof(struct vki_in_addr)];
1701};
1702
1703
1704static
1705Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1706
1707static
1708Int my_socket ( Int domain, Int type, Int protocol );
1709
1710static
1711Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1712 Int addrlen );
1713
1714static
1715UInt my_htonl ( UInt x )
1716{
1717 return
1718 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1719 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1720}
1721
1722static
1723UShort my_htons ( UShort x )
1724{
1725 return
1726 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1727}
1728
1729
1730/* The main function.
1731
1732 Supplied string contains either an ip address "192.168.0.1" or
1733 an ip address and port pair, "192.168.0.1:1500". Parse these,
1734 and return:
1735 -1 if there is a parse error
1736 -2 if no parse error, but specified host:port cannot be opened
1737 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001738 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001739*/
1740Int VG_(connect_via_socket)( UChar* str )
1741{
1742 Int sd, res;
1743 struct vki_sockaddr_in servAddr;
1744 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001745 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001746 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1747 if (!ok)
1748 return -1;
1749
1750 if (0)
1751 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1752 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1753 (ip >> 8) & 0xFF, ip & 0xFF,
1754 (UInt)port );
1755
1756 servAddr.sin_family = AF_INET;
1757 servAddr.sin_addr.s_addr = my_htonl(ip);
1758 servAddr.sin_port = my_htons(port);
1759
1760 /* create socket */
1761 sd = my_socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1762 if (sd < 0) {
1763 /* this shouldn't happen ... nevertheless */
1764 return -2;
1765 }
1766
1767 /* connect to server */
1768 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1769 sizeof(servAddr));
1770 if (res < 0) {
1771 /* connection failed */
1772 return -2;
1773 }
1774
1775 return sd;
1776}
1777
1778
1779/* Let d = one or more digits. Accept either:
1780 d.d.d.d or d.d.d.d:d
1781*/
1782Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1783{
1784# define GET_CH ((*str) ? (*str++) : 0)
1785 UInt ipa, i, j, c, any;
1786 ipa = 0;
1787 for (i = 0; i < 4; i++) {
1788 j = 0;
1789 any = 0;
1790 while (1) {
1791 c = GET_CH;
1792 if (c < '0' || c > '9') break;
1793 j = 10 * j + (int)(c - '0');
1794 any = 1;
1795 }
1796 if (any == 0 || j > 255) goto syntaxerr;
1797 ipa = (ipa << 8) + j;
1798 if (i <= 2 && c != '.') goto syntaxerr;
1799 }
1800 if (c == 0 || c == ':')
1801 *ip_addr = ipa;
1802 if (c == 0) goto ok;
1803 if (c != ':') goto syntaxerr;
1804 j = 0;
1805 any = 0;
1806 while (1) {
1807 c = GET_CH;
1808 if (c < '0' || c > '9') break;
1809 j = j * 10 + (int)(c - '0');
1810 any = 1;
1811 if (j > 65535) goto syntaxerr;
1812 }
1813 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001814 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001815 *port = (UShort)j;
1816 ok:
1817 return 1;
1818 syntaxerr:
1819 return 0;
1820# undef GET_CH
1821}
1822
1823
1824static
1825Int my_socket ( Int domain, Int type, Int protocol )
1826{
1827 Int res;
1828 UInt args[3];
1829 args[0] = domain;
1830 args[1] = type;
1831 args[2] = protocol;
jsgf855d93d2003-10-13 22:26:55 +00001832 res = VG_(do_syscall)(__NR_socketcall, SYS_SOCKET, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001833 if (VG_(is_kerror)(res))
1834 res = -1;
1835 return res;
1836}
1837
1838static
1839Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1840 Int addrlen )
1841{
1842 Int res;
1843 UInt args[3];
1844 args[0] = sockfd;
1845 args[1] = (UInt)serv_addr;
1846 args[2] = addrlen;
jsgf855d93d2003-10-13 22:26:55 +00001847 res = VG_(do_syscall)(__NR_socketcall, SYS_CONNECT, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001848 if (VG_(is_kerror)(res))
1849 res = -1;
1850 return res;
1851}
1852
1853Int VG_(write_socket)( Int sd, void *msg, Int count )
1854{
1855 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001856
1857 /* Requests not to send SIGPIPE on errors on stream oriented
1858 sockets when the other end breaks the connection. The EPIPE
1859 error is still returned. */
1860 Int flags = MSG_NOSIGNAL;
1861
sewardj73cf3bc2002-11-03 03:20:15 +00001862 Int res;
1863 UInt args[4];
1864 args[0] = sd;
1865 args[1] = (UInt)msg;
1866 args[2] = count;
1867 args[3] = flags;
jsgf855d93d2003-10-13 22:26:55 +00001868 res = VG_(do_syscall)(__NR_socketcall, SYS_SEND, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001869 if (VG_(is_kerror)(res))
1870 res = -1;
1871 return res;
1872}
1873
rjwalshf5f536f2003-11-17 17:45:00 +00001874Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1875{
1876 Int res;
1877 UInt args[3];
1878 args[0] = sd;
1879 args[1] = (UInt)name;
1880 args[2] = (UInt)namelen;
1881 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKNAME, (UInt)&args);
1882 if(VG_(is_kerror)(res))
1883 res = -1;
1884 return res;
1885}
1886
1887Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1888{
1889 Int res;
1890 UInt args[3];
1891 args[0] = sd;
1892 args[1] = (UInt)name;
1893 args[2] = (UInt)namelen;
1894 res = VG_(do_syscall)(__NR_socketcall, SYS_GETPEERNAME, (UInt)&args);
1895 if(VG_(is_kerror)(res))
1896 res = -1;
1897 return res;
1898}
1899
1900Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1901 Int *optlen)
1902{
1903 Int res;
1904 UInt args[5];
1905 args[0] = sd;
1906 args[1] = (UInt)level;
1907 args[2] = (UInt)optname;
1908 args[3] = (UInt)optval;
1909 args[4] = (UInt)optlen;
1910 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKOPT, (UInt)&args);
1911 if(VG_(is_kerror)(res))
1912 res = -1;
1913 return res;
1914}
1915
sewardjde4a1d02002-03-22 01:27:54 +00001916
1917/*--------------------------------------------------------------------*/
1918/*--- end vg_mylibc.c ---*/
1919/*--------------------------------------------------------------------*/