blob: ef39f73794c335751d313f1dce1e0f417abd9910 [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
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 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
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000034
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
fitzhardingeb50068f2004-02-24 23:42:55 +0000247static Int munmap_inner(void *start, UInt length)
248{
249 return VG_(do_syscall)(__NR_munmap, (UInt)start, (UInt)length );
250}
251
252static Addr mmap_inner(void *start, UInt length, UInt prot, UInt flags, UInt fd, UInt offset)
253{
254 UInt args[6];
255
256 args[0] = (UInt)start;
257 args[1] = length;
258 args[2] = prot;
259 args[3] = flags & ~(VKI_MAP_NOSYMS|VKI_MAP_CLIENT);
260 args[4] = fd;
261 args[5] = offset;
262
263 return VG_(do_syscall)(__NR_mmap, (UInt)(&(args[0])) );
264}
265
sewardjde4a1d02002-03-22 01:27:54 +0000266/* Returns -1 on failure. */
nethercoteb4250ae2004-07-10 16:50:09 +0000267void* VG_(mmap)( void* start, UInt length,
268 UInt prot, UInt flags, UInt sf_flags, UInt fd, UInt offset)
sewardjde4a1d02002-03-22 01:27:54 +0000269{
fitzhardinge98abfc72003-12-16 02:05:15 +0000270 Addr res;
fitzhardinge98abfc72003-12-16 02:05:15 +0000271
272 if (!(flags & VKI_MAP_FIXED)) {
273 start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
fitzhardinge98abfc72003-12-16 02:05:15 +0000274
275 flags |= VKI_MAP_FIXED;
276 }
nethercoteb4250ae2004-07-10 16:50:09 +0000277 if (start == 0)
278 return (void *)-1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000279
fitzhardingeb50068f2004-02-24 23:42:55 +0000280 res = mmap_inner(start, length, prot, flags, fd, offset);
fitzhardinge98abfc72003-12-16 02:05:15 +0000281
nethercoteb4250ae2004-07-10 16:50:09 +0000282 // Check it ended up in the right place.
fitzhardinge98abfc72003-12-16 02:05:15 +0000283 if (!VG_(is_kerror)(res)) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000284 if (flags & VKI_MAP_CLIENT) {
nethercoteb4250ae2004-07-10 16:50:09 +0000285 vg_assert(VG_(client_base) <= res && res+length < VG_(client_end));
fitzhardinge98abfc72003-12-16 02:05:15 +0000286 } else {
nethercotefb583e22004-09-07 23:15:37 +0000287 vg_assert(VG_(valgrind_base) <= res && res+length-1 <= VG_(valgrind_last));
fitzhardinge98abfc72003-12-16 02:05:15 +0000288 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000289
nethercoteb4250ae2004-07-10 16:50:09 +0000290 sf_flags |= SF_MMAP;
291 if ( flags & VKI_MAP_FIXED) sf_flags |= SF_FIXED;
292 if ( flags & VKI_MAP_SHARED) sf_flags |= SF_SHARED;
293 if (!(flags & VKI_MAP_ANONYMOUS)) sf_flags |= SF_FILE;
294 if (!(flags & VKI_MAP_CLIENT)) sf_flags |= SF_VALGRIND;
295 if ( flags & VKI_MAP_NOSYMS) sf_flags |= SF_NOSYMS;
296
297 VG_(map_fd_segment)(res, length, prot, sf_flags, fd, offset, NULL);
298 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000299
sewardjde4a1d02002-03-22 01:27:54 +0000300 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
301}
302
303/* Returns -1 on failure. */
304Int VG_(munmap)( void* start, Int length )
305{
fitzhardingeb50068f2004-02-24 23:42:55 +0000306 Int res = munmap_inner(start, length);
fitzhardinge920d04e2003-12-20 18:19:50 +0000307 if (!VG_(is_kerror)(res))
fitzhardinge98abfc72003-12-16 02:05:15 +0000308 VG_(unmap_range)((Addr)start, length);
309 return VG_(is_kerror)(res) ? -1 : 0;
310}
311
312Int VG_(mprotect)( void *start, Int length, UInt prot )
313{
314 Int res = VG_(do_syscall)(__NR_mprotect, (UInt)start, (UInt)length, prot );
315 if (!VG_(is_kerror)(res))
316 VG_(mprotect_range)((Addr)start, length, prot);
sewardjde4a1d02002-03-22 01:27:54 +0000317 return VG_(is_kerror)(res) ? -1 : 0;
318}
319
320void VG_(exit)( Int status )
321{
jsgf855d93d2003-10-13 22:26:55 +0000322 (void)VG_(do_syscall)(__NR_exit_group, (UInt)status );
323 (void)VG_(do_syscall)(__NR_exit, (UInt)status );
sewardjde4a1d02002-03-22 01:27:54 +0000324 /* Why are we still alive here? */
325 /*NOTREACHED*/
jsgf855d93d2003-10-13 22:26:55 +0000326 *(volatile Int *)0 = 'x';
sewardjde4a1d02002-03-22 01:27:54 +0000327 vg_assert(2+2 == 5);
328}
329
sewardj2e93c502002-04-12 11:12:52 +0000330/* Returns -1 on error. */
331Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
332{
jsgf855d93d2003-10-13 22:26:55 +0000333 Int res = VG_(do_syscall)(__NR_fcntl, fd, cmd, arg);
sewardj2e93c502002-04-12 11:12:52 +0000334 return VG_(is_kerror)(res) ? -1 : res;
335}
336
jsgf855d93d2003-10-13 22:26:55 +0000337Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
338{
339 Int res = VG_(do_syscall)(__NR_poll, ufds, nfds, timeout);
340
341 return res;
342}
343
sewardj2e93c502002-04-12 11:12:52 +0000344
sewardjde4a1d02002-03-22 01:27:54 +0000345/* ---------------------------------------------------------------------
346 printf implementation. The key function, vg_vprintf(), emits chars
347 into a caller-supplied function. Distantly derived from:
348
349 vprintf replacement for Checker.
350 Copyright 1993, 1994, 1995 Tristan Gingold
351 Written September 1993 Tristan Gingold
352 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
353
354 (Checker itself was GPL'd.)
355 ------------------------------------------------------------------ */
356
357
358/* Some flags. */
359#define VG_MSG_SIGNED 1 /* The value is signed. */
360#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
361#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
sewardj78e3cd92002-10-22 04:45:48 +0000362#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
njn607adfc2003-09-30 14:15:44 +0000363#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
sewardjde4a1d02002-03-22 01:27:54 +0000364
365/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000366static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000367myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
368 Bool capitalise )
369{
370# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000371 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000372 Int i, extra;
373 Int len = VG_(strlen)(str);
374
375 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000376 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000377 for (i = 0; i < len; i++)
378 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000379 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000380 }
381
382 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000383 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000384 for (i = 0; i < width; i++)
385 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000386 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000387 }
388
389 extra = width - len;
390 if (flags & VG_MSG_LJUSTIFY) {
sewardj78e3cd92002-10-22 04:45:48 +0000391 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000392 for (i = 0; i < extra; i++)
393 send(' ');
394 }
sewardj78e3cd92002-10-22 04:45:48 +0000395 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000396 for (i = 0; i < len; i++)
397 send(MAYBE_TOUPPER(str[i]));
398 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000399 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000400 for (i = 0; i < extra; i++)
401 send(' ');
402 }
403
404# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000405
406 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000407}
408
409/* Write P into the buffer according to these args:
410 * If SIGN is true, p is a signed.
411 * BASE is the base.
412 * If WITH_ZERO is true, '0' must be added.
413 * WIDTH is the width of the field.
414 */
sewardj78e3cd92002-10-22 04:45:48 +0000415static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000416myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
417{
418 Char buf[40];
419 Int ind = 0;
njn607adfc2003-09-30 14:15:44 +0000420 Int i, nc = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000421 Bool neg = False;
422 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000423 UInt ret = 0;
424
sewardjde4a1d02002-03-22 01:27:54 +0000425 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000426 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000427
428 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
429 p = - (Long)p;
430 neg = True;
431 }
432
433 if (p == 0)
434 buf[ind++] = '0';
435 else {
436 while (p > 0) {
njn607adfc2003-09-30 14:15:44 +0000437 if (flags & VG_MSG_COMMA && 10 == base &&
438 0 == (ind-nc) % 3 && 0 != ind)
439 {
440 buf[ind++] = ',';
441 nc++;
442 }
sewardjde4a1d02002-03-22 01:27:54 +0000443 buf[ind++] = digits[p % base];
444 p /= base;
njn607adfc2003-09-30 14:15:44 +0000445 }
sewardjde4a1d02002-03-22 01:27:54 +0000446 }
447
448 if (neg)
449 buf[ind++] = '-';
450
451 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
452 for(; ind < width; ind++) {
453 vg_assert(ind < 39);
454 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
455 }
456 }
457
458 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000459 ret += ind;
njn607adfc2003-09-30 14:15:44 +0000460 for (i = ind -1; i >= 0; i--) {
sewardjde4a1d02002-03-22 01:27:54 +0000461 send(buf[i]);
njn607adfc2003-09-30 14:15:44 +0000462 }
sewardjde4a1d02002-03-22 01:27:54 +0000463 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000464 for(; ind < width; ind++) {
465 ret++;
njn607adfc2003-09-30 14:15:44 +0000466 send(' '); // Never pad with zeroes on RHS -- changes the value!
sewardj78e3cd92002-10-22 04:45:48 +0000467 }
sewardjde4a1d02002-03-22 01:27:54 +0000468 }
sewardj78e3cd92002-10-22 04:45:48 +0000469 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000470}
471
472
473/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000474UInt
sewardjde4a1d02002-03-22 01:27:54 +0000475VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
476{
sewardj78e3cd92002-10-22 04:45:48 +0000477 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000478 int i;
479 int flags;
480 int width;
481 Bool is_long;
482
483 /* We assume that vargs has already been initialised by the
484 caller, using va_start, and that the caller will similarly
485 clean up with va_end.
486 */
487
488 for (i = 0; format[i] != 0; i++) {
489 if (format[i] != '%') {
490 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000491 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000492 continue;
493 }
494 i++;
495 /* A '%' has been found. Ignore a trailing %. */
496 if (format[i] == 0)
497 break;
498 if (format[i] == '%') {
499 /* `%%' is replaced by `%'. */
500 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000501 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000502 continue;
503 }
504 flags = 0;
505 is_long = False;
506 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000507 if (format[i] == '(') {
508 flags |= VG_MSG_PAREN;
509 i++;
510 }
njn607adfc2003-09-30 14:15:44 +0000511 /* If ',' follows '%', commas will be inserted. */
512 if (format[i] == ',') {
513 flags |= VG_MSG_COMMA;
514 i++;
515 }
sewardjde4a1d02002-03-22 01:27:54 +0000516 /* If '-' follows '%', justify on the left. */
517 if (format[i] == '-') {
518 flags |= VG_MSG_LJUSTIFY;
519 i++;
520 }
521 /* If '0' follows '%', pads will be inserted. */
522 if (format[i] == '0') {
523 flags |= VG_MSG_ZJUSTIFY;
524 i++;
525 }
526 /* Compute the field length. */
527 while (format[i] >= '0' && format[i] <= '9') {
528 width *= 10;
529 width += format[i++] - '0';
530 }
531 while (format[i] == 'l') {
532 i++;
533 is_long = True;
534 }
535
536 switch (format[i]) {
537 case 'd': /* %d */
538 flags |= VG_MSG_SIGNED;
539 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000540 ret += myvprintf_int64(send, flags, 10, width,
541 (ULong)(va_arg (vargs, Long)));
sewardjde4a1d02002-03-22 01:27:54 +0000542 else
sewardj78e3cd92002-10-22 04:45:48 +0000543 ret += myvprintf_int64(send, flags, 10, width,
544 (ULong)(va_arg (vargs, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000545 break;
546 case 'u': /* %u */
547 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000548 ret += myvprintf_int64(send, flags, 10, width,
549 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000550 else
sewardj78e3cd92002-10-22 04:45:48 +0000551 ret += myvprintf_int64(send, flags, 10, width,
552 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000553 break;
554 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000555 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000556 send('0');
557 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000558 ret += myvprintf_int64(send, flags, 16, width,
559 (ULong)((UInt)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000560 break;
561 case 'x': /* %x */
562 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000563 ret += myvprintf_int64(send, flags, 16, width,
564 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000565 else
sewardj78e3cd92002-10-22 04:45:48 +0000566 ret += myvprintf_int64(send, flags, 16, width,
567 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000568 break;
569 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000570 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000571 send(va_arg (vargs, int));
572 break;
573 case 's': case 'S': { /* %s */
574 char *str = va_arg (vargs, char *);
575 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000576 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000577 break;
sewardj78e3cd92002-10-22 04:45:48 +0000578 }
579 case 'y': { /* %y - print symbol */
580 Char buf[100];
581 Char *cp = buf;
582 Addr a = va_arg(vargs, Addr);
583
584 if (flags & VG_MSG_PAREN)
585 *cp++ = '(';
sewardj6e008cb2002-12-15 13:11:39 +0000586 if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
sewardj78e3cd92002-10-22 04:45:48 +0000587 if (flags & VG_MSG_PAREN) {
588 cp += VG_(strlen)(cp);
589 *cp++ = ')';
590 *cp = '\0';
591 }
592 ret += myvprintf_str(send, flags, width, buf, 0);
593 }
594
595 break;
596 }
sewardjde4a1d02002-03-22 01:27:54 +0000597 default:
598 break;
599 }
600 }
sewardj78e3cd92002-10-22 04:45:48 +0000601 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000602}
603
604
605/* A general replacement for printf(). Note that only low-level
606 debugging info should be sent via here. The official route is to
607 to use vg_message(). This interface is deprecated.
608*/
609static char myprintf_buf[100];
610static int n_myprintf_buf;
611
612static void add_to_myprintf_buf ( Char c )
613{
614 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
nethercotef8548672004-06-21 12:42:35 +0000615 if (VG_(clo_log_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000616 VG_(send_bytes_to_logging_sink)(
617 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000618 }
sewardjde4a1d02002-03-22 01:27:54 +0000619 n_myprintf_buf = 0;
620 myprintf_buf[n_myprintf_buf] = 0;
621 }
622 myprintf_buf[n_myprintf_buf++] = c;
623 myprintf_buf[n_myprintf_buf] = 0;
624}
625
sewardj78e3cd92002-10-22 04:45:48 +0000626UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000627{
sewardj78e3cd92002-10-22 04:45:48 +0000628 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000629 va_list vargs;
630 va_start(vargs,format);
631
632 n_myprintf_buf = 0;
633 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000634 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000635
nethercotef8548672004-06-21 12:42:35 +0000636 if (n_myprintf_buf > 0 && VG_(clo_log_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000637 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000638 }
sewardjde4a1d02002-03-22 01:27:54 +0000639
640 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000641
642 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000643}
644
sewardjde4a1d02002-03-22 01:27:54 +0000645/* A general replacement for sprintf(). */
thughes4ad52d02004-06-27 17:37:21 +0000646
647static Char *vg_sprintf_ptr;
648
649static void add_to_vg_sprintf_buf ( Char c )
650{
651 *vg_sprintf_ptr++ = c;
652}
653
sewardj78e3cd92002-10-22 04:45:48 +0000654UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000655{
sewardj05bcdcb2003-05-18 10:05:38 +0000656 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000657 va_list vargs;
thughes4ad52d02004-06-27 17:37:21 +0000658
659 vg_sprintf_ptr = buf;
660
sewardjde4a1d02002-03-22 01:27:54 +0000661 va_start(vargs,format);
662
sewardj78e3cd92002-10-22 04:45:48 +0000663 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000664 add_to_vg_sprintf_buf(0);
665
666 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000667
668 vg_assert(VG_(strlen)(buf) == ret);
669 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000670}
671
672
673/* ---------------------------------------------------------------------
674 Misc str* functions.
675 ------------------------------------------------------------------ */
676
677Bool VG_(isspace) ( Char c )
678{
679 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
680}
681
njn7cf0bd32002-06-08 13:36:03 +0000682Bool VG_(isdigit) ( Char c )
683{
684 return (c >= '0' && c <= '9');
685}
sewardjde4a1d02002-03-22 01:27:54 +0000686
687Int VG_(strlen) ( const Char* str )
688{
689 Int i = 0;
690 while (str[i] != 0) i++;
691 return i;
692}
693
694
695Long VG_(atoll) ( Char* str )
696{
697 Bool neg = False;
698 Long n = 0;
699 if (*str == '-') { str++; neg = True; };
700 while (*str >= '0' && *str <= '9') {
701 n = 10*n + (Long)(*str - '0');
702 str++;
703 }
704 if (neg) n = -n;
705 return n;
706}
707
708
njn25e49d8e72002-09-23 09:36:25 +0000709Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000710{
711 Bool neg = False;
712 Long n = 0;
713 if (*str == '-') { str++; neg = True; };
714 while (True) {
715 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000716 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000717 }
718 else
njn25e49d8e72002-09-23 09:36:25 +0000719 if (*str >= 'A' && *str <= 'F') {
720 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000721 }
722 else
njn25e49d8e72002-09-23 09:36:25 +0000723 if (*str >= 'a' && *str <= 'f') {
724 n = 16*n + (Long)((*str - 'a') + 10);
725 }
726 else {
727 break;
728 }
729 str++;
730 }
731 if (neg) n = -n;
732 return n;
733}
734
735Long VG_(atoll36) ( UInt base, Char* str )
736{
737 Bool neg = False;
738 Long n = 0;
739 vg_assert(base >= 2 && base <= 36);
740 if (*str == '-') { str++; neg = True; };
741 while (True) {
sewardj05bcdcb2003-05-18 10:05:38 +0000742 if (*str >= '0'
743 && *str <= (Char)('9' - (10 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000744 n = base*n + (Long)(*str - '0');
745 }
746 else
sewardj05bcdcb2003-05-18 10:05:38 +0000747 if (base > 10 && *str >= 'A'
748 && *str <= (Char)('Z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000749 n = base*n + (Long)((*str - 'A') + 10);
750 }
751 else
sewardj05bcdcb2003-05-18 10:05:38 +0000752 if (base > 10 && *str >= 'a'
753 && *str <= (Char)('z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000754 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000755 }
756 else {
757 break;
758 }
759 str++;
760 }
761 if (neg) n = -n;
762 return n;
763}
764
765
sewardjde4a1d02002-03-22 01:27:54 +0000766Char* VG_(strcat) ( Char* dest, const Char* src )
767{
768 Char* dest_orig = dest;
769 while (*dest) dest++;
770 while (*src) *dest++ = *src++;
771 *dest = 0;
772 return dest_orig;
773}
774
775
776Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
777{
778 Char* dest_orig = dest;
779 while (*dest) dest++;
780 while (*src && n > 0) { *dest++ = *src++; n--; }
781 *dest = 0;
782 return dest_orig;
783}
784
785
786Char* VG_(strpbrk) ( const Char* s, const Char* accept )
787{
788 const Char* a;
789 while (*s) {
790 a = accept;
791 while (*a)
792 if (*a++ == *s)
793 return (Char *) s;
794 s++;
795 }
796 return NULL;
797}
798
799
800Char* VG_(strcpy) ( Char* dest, const Char* src )
801{
802 Char* dest_orig = dest;
803 while (*src) *dest++ = *src++;
804 *dest = 0;
805 return dest_orig;
806}
807
808
809/* Copy bytes, not overrunning the end of dest and always ensuring
810 zero termination. */
811void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
812{
813 Int i;
814 vg_assert(ndest > 0);
815 i = 0;
816 dest[i] = 0;
817 while (True) {
818 if (src[i] == 0) return;
819 if (i >= ndest-1) return;
820 dest[i] = src[i];
821 i++;
822 dest[i] = 0;
823 }
824}
825
826
njn25e49d8e72002-09-23 09:36:25 +0000827Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000828{
njn25e49d8e72002-09-23 09:36:25 +0000829 Int i = 0;
830 while (True) {
831 if (i >= ndest) return dest; /* reached limit */
832 dest[i] = src[i];
833 if (src[i++] == 0) {
834 /* reached NUL; pad rest with zeroes as required */
835 while (i < ndest) dest[i++] = 0;
836 return dest;
837 }
838 }
sewardjde4a1d02002-03-22 01:27:54 +0000839}
840
841
842Int VG_(strcmp) ( const Char* s1, const Char* s2 )
843{
844 while (True) {
845 if (*s1 == 0 && *s2 == 0) return 0;
846 if (*s1 == 0) return -1;
847 if (*s2 == 0) return 1;
848
849 if (*(UChar*)s1 < *(UChar*)s2) return -1;
850 if (*(UChar*)s1 > *(UChar*)s2) return 1;
851
852 s1++; s2++;
853 }
854}
855
856
857Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
858{
859 while (True) {
860 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
861 if (VG_(isspace)(*s1)) return -1;
862 if (VG_(isspace)(*s2)) return 1;
863
864 if (*(UChar*)s1 < *(UChar*)s2) return -1;
865 if (*(UChar*)s1 > *(UChar*)s2) return 1;
866
867 s1++; s2++;
868 }
869}
870
871
872Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
873{
874 Int n = 0;
875 while (True) {
876 if (n >= nmax) return 0;
877 if (*s1 == 0 && *s2 == 0) return 0;
878 if (*s1 == 0) return -1;
879 if (*s2 == 0) return 1;
880
881 if (*(UChar*)s1 < *(UChar*)s2) return -1;
882 if (*(UChar*)s1 > *(UChar*)s2) return 1;
883
884 s1++; s2++; n++;
885 }
886}
887
888
889Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
890{
891 Int n = 0;
892 while (True) {
893 if (n >= nmax) return 0;
894 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
895 if (VG_(isspace)(*s1)) return -1;
896 if (VG_(isspace)(*s2)) return 1;
897
898 if (*(UChar*)s1 < *(UChar*)s2) return -1;
899 if (*(UChar*)s1 > *(UChar*)s2) return 1;
900
901 s1++; s2++; n++;
902 }
903}
904
905
906Char* VG_(strstr) ( const Char* haystack, Char* needle )
907{
sewardj3984b852002-05-12 03:00:17 +0000908 Int n;
909 if (haystack == NULL)
910 return NULL;
911 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000912 while (True) {
913 if (haystack[0] == 0)
914 return NULL;
915 if (VG_(strncmp)(haystack, needle, n) == 0)
916 return (Char*)haystack;
917 haystack++;
918 }
919}
920
921
922Char* VG_(strchr) ( const Char* s, Char c )
923{
924 while (True) {
925 if (*s == c) return (Char*)s;
926 if (*s == 0) return NULL;
927 s++;
928 }
929}
930
931
thughesc0b63de2004-06-13 09:55:22 +0000932Char* VG_(strrchr) ( const Char* s, Char c )
933{
934 Int n = VG_(strlen)(s);
935 while (--n > 0) {
936 if (s[n] == c) return (Char*)s + n;
937 }
938 return NULL;
939}
940
941
sewardj7ab2aca2002-10-20 19:40:32 +0000942void* VG_(memcpy) ( void *dest, const void *src, Int sz )
943{
944 const Char *s = (const Char *)src;
945 Char *d = (Char *)dest;
946 vg_assert(sz >= 0);
947
948 while (sz--)
949 *d++ = *s++;
950
951 return dest;
952}
953
954
955void* VG_(memset) ( void *dest, Int c, Int sz )
956{
957 Char *d = (Char *)dest;
958 vg_assert(sz >= 0);
959
960 while (sz--)
961 *d++ = c;
962
963 return dest;
964}
965
njn6d68e792003-02-24 10:49:08 +0000966Int VG_(memcmp) ( const void* s1, const void* s2, Int n )
967{
968 Int res;
njnfa4690b2003-02-24 21:43:05 +0000969 UChar a0;
970 UChar b0;
njn6d68e792003-02-24 10:49:08 +0000971 vg_assert(n >= 0);
972
973 while (n != 0) {
njnfa4690b2003-02-24 21:43:05 +0000974 a0 = ((UChar *) s1)[0];
975 b0 = ((UChar *) s2)[0];
njn6d68e792003-02-24 10:49:08 +0000976 s1 += 1;
977 s2 += 1;
978 res = a0 - b0;
979 if (res != 0)
980 return res;
981 n -= 1;
982 }
983 return 0;
984}
sewardj7ab2aca2002-10-20 19:40:32 +0000985
sewardjde4a1d02002-03-22 01:27:54 +0000986Char VG_(toupper) ( Char c )
987{
988 if (c >= 'a' && c <= 'z')
989 return c + ('A' - 'a');
990 else
991 return c;
992}
993
994
njn25e49d8e72002-09-23 09:36:25 +0000995/* Inline just for the wrapper VG_(strdup) below */
996__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +0000997{
njn25e49d8e72002-09-23 09:36:25 +0000998 Int i;
fitzhardingea7728472003-12-16 01:48:38 +0000999 Int len;
1000 Char* res;
1001
1002 if (s == NULL)
1003 return NULL;
1004
1005 len = VG_(strlen)(s) + 1;
1006 res = VG_(arena_malloc) (aid, len);
1007
njn25e49d8e72002-09-23 09:36:25 +00001008 for (i = 0; i < len; i++)
1009 res[i] = s[i];
1010 return res;
sewardjde4a1d02002-03-22 01:27:54 +00001011}
1012
nethercote7cc9c232004-01-21 15:08:04 +00001013/* Wrapper to avoid exposing tools to ArenaId's */
njn25e49d8e72002-09-23 09:36:25 +00001014Char* VG_(strdup) ( const Char* s )
1015{
nethercote60f5b822004-01-26 17:24:42 +00001016 return VG_(arena_strdup) ( VG_AR_TOOL, s );
njn25e49d8e72002-09-23 09:36:25 +00001017}
sewardjde4a1d02002-03-22 01:27:54 +00001018
1019/* ---------------------------------------------------------------------
1020 A simple string matching routine, purloined from Hugs98.
1021 `*' matches any sequence of zero or more characters
1022 `?' matches any single character exactly
1023 `\c' matches the character c only (ignoring special chars)
1024 c matches the character c only
1025 ------------------------------------------------------------------ */
1026
1027/* Keep track of recursion depth. */
1028static Int recDepth;
1029
fitzhardinge98abfc72003-12-16 02:05:15 +00001030static Bool string_match_wrk ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001031{
sewardje54b69d2003-07-06 01:14:42 +00001032 vg_assert(recDepth >= 0 && recDepth < 500);
sewardjde4a1d02002-03-22 01:27:54 +00001033 recDepth++;
1034 for (;;) {
1035 switch (*pat) {
1036 case '\0' : return (*str=='\0');
1037 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001038 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001039 recDepth--;
1040 return True;
1041 }
1042 } while (*str++);
1043 recDepth--;
1044 return False;
1045 case '?' : if (*str++=='\0') {
1046 recDepth--;
1047 return False;
1048 }
1049 pat++;
1050 break;
1051 case '\\' : if (*++pat == '\0') {
1052 recDepth--;
1053 return False; /* spurious trailing \ in pattern */
1054 }
1055 /* falls through to ... */
1056 default : if (*pat++ != *str++) {
1057 recDepth--;
1058 return False;
1059 }
1060 break;
1061 }
1062 }
1063}
1064
fitzhardinge98abfc72003-12-16 02:05:15 +00001065Bool VG_(string_match) ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001066{
1067 Bool b;
1068 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001069 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001070 /*
1071 VG_(printf)("%s %s %s\n",
1072 b?"TRUE ":"FALSE", pat, str);
1073 */
1074 return b;
1075}
1076
1077
1078/* ---------------------------------------------------------------------
1079 Assertery.
1080 ------------------------------------------------------------------ */
1081
jsgf855d93d2003-10-13 22:26:55 +00001082/* Fake up an ExeContext which is of our actual real CPU state, so we
1083 can print a stack trace. This isn't terribly useful in the case
1084 where we were killed by a signal, since we just get a backtrace
1085 into the signal handler. Also, it could be somewhat risky if we
1086 actully got the panic/exception within the execontext/stack
1087 dump/symtab code. But it's better than nothing. */
1088static inline ExeContext *get_real_execontext(Addr ret)
1089{
1090 ExeContext *ec;
fitzhardingea09a1b52003-11-07 23:09:48 +00001091 Addr esp, ebp;
nethercote759dda32004-08-07 18:16:56 +00001092 Addr stacktop, sigstack_low, sigstack_high;
jsgf855d93d2003-10-13 22:26:55 +00001093
fitzhardingea09a1b52003-11-07 23:09:48 +00001094 asm("movl %%ebp, %0; movl %%esp, %1" : "=r" (ebp), "=r" (esp));
nethercote820bd8c2004-09-07 23:04:49 +00001095 stacktop = VG_(valgrind_last);
nethercote759dda32004-08-07 18:16:56 +00001096 VG_(get_sigstack_bounds)( &sigstack_low, &sigstack_high );
1097 if (esp >= sigstack_low && esp < sigstack_high)
1098 stacktop = sigstack_high;
jsgf855d93d2003-10-13 22:26:55 +00001099
1100 ec = VG_(get_ExeContext2)(ret, ebp, esp, stacktop);
1101
1102 return ec;
1103}
1104
njne427a662002-10-02 11:08:25 +00001105__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001106static void report_and_quit ( const Char* report )
njne427a662002-10-02 11:08:25 +00001107{
jsgf855d93d2003-10-13 22:26:55 +00001108 ExeContext *ec = get_real_execontext((Addr)__builtin_return_address(0));
1109 VG_(pp_ExeContext)(ec);
1110
njne427a662002-10-02 11:08:25 +00001111 VG_(pp_sched_status)();
sewardj366ee1e2003-04-26 22:36:42 +00001112 VG_(printf)("\n");
1113 VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
1114 VG_(printf)("It contains workarounds to several common problems.\n");
1115 VG_(printf)("\n");
1116 VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
1117 report);
1118 VG_(printf)("In the bug report, send all the above text, the valgrind\n");
sewardj96330bd2003-04-27 23:46:21 +00001119 VG_(printf)("version, and what Linux distro you are using. Thanks.\n\n");
njne427a662002-10-02 11:08:25 +00001120 VG_(exit)(1);
1121}
1122
1123__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001124static void assert_fail ( const Char* expr, const Char* name, const Char* report,
1125 const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001126{
sewardj018f7622002-05-15 21:13:39 +00001127 static Bool entered = False;
1128 if (entered)
1129 VG_(exit)(2);
1130 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001131 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001132 name, file, line, fn, expr );
1133 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001134}
1135
daywalker3222e0a2003-09-18 01:39:50 +00001136void VG_(skin_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001137{
njnd04b7c62002-10-03 14:05:52 +00001138 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001139 file, line, fn);
1140}
1141
daywalker3222e0a2003-09-18 01:39:50 +00001142void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
njne427a662002-10-02 11:08:25 +00001143{
nethercote421281e2003-11-20 16:20:55 +00001144 assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn);
njne427a662002-10-02 11:08:25 +00001145}
1146
1147__attribute__ ((noreturn))
1148static void panic ( Char* name, Char* report, Char* str )
1149{
1150 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001151 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
njne427a662002-10-02 11:08:25 +00001152 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001153}
1154
njne427a662002-10-02 11:08:25 +00001155void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001156{
nethercote421281e2003-11-20 16:20:55 +00001157 panic("valgrind", VG_BUGS_TO, str);
njn25e49d8e72002-09-23 09:36:25 +00001158}
1159
njne427a662002-10-02 11:08:25 +00001160void VG_(skin_panic) ( Char* str )
1161{
njnd04b7c62002-10-03 14:05:52 +00001162 panic(VG_(details).name, VG_(details).bug_reports_to, str);
njne427a662002-10-02 11:08:25 +00001163}
sewardjde4a1d02002-03-22 01:27:54 +00001164
njn13f02932003-04-30 20:23:58 +00001165
sewardjde4a1d02002-03-22 01:27:54 +00001166/* ---------------------------------------------------------------------
1167 Primitive support for reading files.
1168 ------------------------------------------------------------------ */
1169
jsgf855d93d2003-10-13 22:26:55 +00001170static inline Bool fd_exists(Int fd)
1171{
1172 struct vki_stat st;
1173
1174 return VG_(fstat)(fd, &st) == 0;
1175}
1176
1177/* Move an fd into the Valgrind-safe range */
1178Int VG_(safe_fd)(Int oldfd)
1179{
1180 Int newfd;
1181
thughesad1c9562004-06-26 11:27:52 +00001182 vg_assert(VG_(fd_hard_limit) != -1);
fitzhardingeb791a192003-12-18 07:22:44 +00001183
thughesad1c9562004-06-26 11:27:52 +00001184 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
jsgf855d93d2003-10-13 22:26:55 +00001185 if (newfd != -1)
1186 VG_(close)(oldfd);
1187
1188 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
1189
thughesad1c9562004-06-26 11:27:52 +00001190 vg_assert(newfd >= VG_(fd_hard_limit));
jsgf855d93d2003-10-13 22:26:55 +00001191 return newfd;
1192}
1193
1194
1195
sewardjde4a1d02002-03-22 01:27:54 +00001196/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001197Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1198{
sewardjde4a1d02002-03-22 01:27:54 +00001199 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001200
njn25e49d8e72002-09-23 09:36:25 +00001201 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001202 /* This gets a segmentation fault if pathname isn't a valid file.
1203 I don't know why. It seems like the call to open is getting
1204 intercepted and messed with by glibc ... */
1205 /* fd = open( pathname, O_RDONLY ); */
1206 /* ... so we go direct to the horse's mouth, which seems to work
1207 ok: */
jsgf855d93d2003-10-13 22:26:55 +00001208 fd = VG_(do_syscall)(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001209 /* VG_(printf)("result = %d\n", fd); */
jsgff3c3f1a2003-10-14 22:13:28 +00001210 /* return -ve error code */
njn4f9c9342002-04-29 16:03:24 +00001211 return fd;
1212}
sewardjde4a1d02002-03-22 01:27:54 +00001213
jsgf855d93d2003-10-13 22:26:55 +00001214Int VG_(pipe) ( Int fd[2] )
1215{
1216 Int ret = VG_(do_syscall)(__NR_pipe, fd);
1217 return VG_(is_kerror)(ret) ? -1 : 0;
1218}
1219
sewardjde4a1d02002-03-22 01:27:54 +00001220void VG_(close) ( Int fd )
1221{
jsgf855d93d2003-10-13 22:26:55 +00001222 VG_(do_syscall)(__NR_close, fd);
sewardjde4a1d02002-03-22 01:27:54 +00001223}
1224
1225
1226Int VG_(read) ( Int fd, void* buf, Int count)
1227{
1228 Int res;
1229 /* res = read( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001230 res = VG_(do_syscall)(__NR_read, fd, (UInt)buf, count);
1231 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001232 return res;
1233}
1234
jsgf855d93d2003-10-13 22:26:55 +00001235Int VG_(write) ( Int fd, const void* buf, Int count)
sewardjde4a1d02002-03-22 01:27:54 +00001236{
1237 Int res;
1238 /* res = write( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001239 res = VG_(do_syscall)(__NR_write, fd, (UInt)buf, count);
1240 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001241 return res;
1242}
1243
rjwalshf5f536f2003-11-17 17:45:00 +00001244Int VG_(lseek) ( Int fd, Long offset, Int whence)
1245{
1246 Int res;
1247 /* res = lseek( fd, offset, whence ); */
1248 res = VG_(do_syscall)(__NR_lseek, fd, (UInt)offset, whence);
1249 if (VG_(is_kerror)(res)) res = -1;
1250 return res;
1251}
1252
sewardjb3586202002-05-09 17:38:13 +00001253Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1254{
1255 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001256 res = VG_(do_syscall)(__NR_stat, (UInt)file_name, (UInt)buf);
fitzhardingee1c06d82003-10-30 07:21:44 +00001257 return res; /* return -ve error */
njn41557122002-10-14 09:25:37 +00001258}
1259
jsgf855d93d2003-10-13 22:26:55 +00001260Int VG_(fstat) ( Int fd, struct vki_stat* buf )
1261{
1262 Int res;
1263 res = VG_(do_syscall)(__NR_fstat, (UInt)fd, (UInt)buf);
1264 return VG_(is_kerror)(res) ? (-1) : 0;
1265}
1266
1267Int VG_(dup2) ( Int oldfd, Int newfd )
1268{
1269 Int res;
1270 res = VG_(do_syscall)(__NR_dup2, (UInt)oldfd, (UInt)newfd);
1271 return VG_(is_kerror)(res) ? (-1) : res;
1272}
1273
njn41557122002-10-14 09:25:37 +00001274Int VG_(rename) ( Char* old_name, Char* new_name )
1275{
1276 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001277 res = VG_(do_syscall)(__NR_rename, (UInt)old_name, (UInt)new_name);
njn41557122002-10-14 09:25:37 +00001278 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001279}
1280
njn4aca2d22002-10-04 10:29:38 +00001281Int VG_(unlink) ( Char* file_name )
1282{
1283 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001284 res = VG_(do_syscall)(__NR_unlink, (UInt)file_name);
njn41557122002-10-14 09:25:37 +00001285 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001286}
1287
njn13f02932003-04-30 20:23:58 +00001288/* Nb: we do not allow the Linux extension which malloc()s memory for the
1289 buffer if buf==NULL, because we don't want Linux calling malloc() */
1290Char* VG_(getcwd) ( Char* buf, Int size )
1291{
1292 Int res;
1293 vg_assert(buf != NULL);
jsgf855d93d2003-10-13 22:26:55 +00001294 res = VG_(do_syscall)(__NR_getcwd, (UInt)buf, (UInt)size);
njn13f02932003-04-30 20:23:58 +00001295 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1296}
1297
njn99ccf082003-09-30 13:51:23 +00001298/* Alternative version that does allocate the memory. Easier to use. */
1299Bool VG_(getcwd_alloc) ( Char** out )
1300{
1301 UInt size = 4;
1302
1303 *out = NULL;
1304 while (True) {
1305 *out = VG_(malloc)(size);
1306 if (NULL == VG_(getcwd)(*out, size)) {
1307 VG_(free)(*out);
1308 if (size > 65535)
1309 return False;
1310 size *= 2;
1311 } else {
1312 return True;
1313 }
1314 }
1315}
1316
njn13f02932003-04-30 20:23:58 +00001317
1318/* ---------------------------------------------------------------------
1319 Misc functions looking for a proper home.
1320 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001321
nethercoteff9721d2004-01-26 17:10:01 +00001322/* clone the environment */
nethercote85cdd342004-08-01 22:36:40 +00001323static Char **env_clone ( Char **oldenv )
nethercoteff9721d2004-01-26 17:10:01 +00001324{
1325 Char **oldenvp;
1326 Char **newenvp;
1327 Char **newenv;
1328 Int envlen;
1329
1330 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
1331
1332 envlen = oldenvp - oldenv + 1;
1333
1334 newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1335
1336 oldenvp = oldenv;
1337 newenvp = newenv;
1338
1339 while (oldenvp && *oldenvp) {
1340 *newenvp++ = *oldenvp++;
1341 }
1342
1343 *newenvp = *oldenvp;
1344
1345 return newenv;
1346}
1347
fitzhardinge98abfc72003-12-16 02:05:15 +00001348void VG_(env_unsetenv) ( Char **env, const Char *varname )
1349{
1350 Char **from;
1351 Char **to = NULL;
1352 Int len = VG_(strlen)(varname);
1353
1354 for(from = to = env; from && *from; from++) {
1355 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
1356 *to = *from;
1357 to++;
1358 }
1359 }
1360 *to = *from;
1361}
1362
1363/* set the environment; returns the old env if a new one was allocated */
1364Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
1365{
1366 Char **env = (*envp);
1367 Char **cpp;
1368 Int len = VG_(strlen)(varname);
1369 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, len + VG_(strlen)(val) + 2);
1370 Char **oldenv = NULL;
1371
1372 VG_(sprintf)(valstr, "%s=%s", varname, val);
1373
1374 for(cpp = env; cpp && *cpp; cpp++) {
1375 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
1376 *cpp = valstr;
1377 return oldenv;
1378 }
1379 }
1380
1381 if (env == NULL) {
1382 env = VG_(arena_malloc)(VG_AR_CORE, sizeof(Char **) * 2);
1383 env[0] = valstr;
1384 env[1] = NULL;
1385
1386 *envp = env;
1387
1388 } else {
1389 Int envlen = (cpp-env) + 2;
1390 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1391
1392 for(cpp = newenv; *env; )
1393 *cpp++ = *env++;
1394 *cpp++ = valstr;
1395 *cpp++ = NULL;
1396
1397 oldenv = *envp;
1398
1399 *envp = newenv;
1400 }
1401
1402 return oldenv;
1403}
1404
nethercote85cdd342004-08-01 22:36:40 +00001405/* We do getenv without libc's help by snooping around in
1406 VG_(client_envp) as determined at startup time. */
1407Char *VG_(getenv)(Char *varname)
sewardjde4a1d02002-03-22 01:27:54 +00001408{
1409 Int i, n;
1410 n = VG_(strlen)(varname);
nethercote85cdd342004-08-01 22:36:40 +00001411 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1412 Char* s = VG_(client_envp)[i];
sewardjde4a1d02002-03-22 01:27:54 +00001413 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1414 return & s[n+1];
1415 }
1416 }
1417 return NULL;
1418}
1419
rjwalshf5f536f2003-11-17 17:45:00 +00001420/* Support for getrlimit. */
1421Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
1422{
1423 Int res;
1424 /* res = getrlimit( resource, rlim ); */
1425 res = VG_(do_syscall)(__NR_getrlimit, (UInt)resource, (UInt)rlim);
1426 if(VG_(is_kerror)(res)) res = -1;
1427 return res;
1428}
1429
1430
fitzhardingef0046f22003-12-18 02:39:22 +00001431/* Support for setrlimit. */
1432Int VG_(setrlimit) (Int resource, struct vki_rlimit *rlim)
1433{
1434 Int res;
1435 /* res = setrlimit( resource, rlim ); */
1436 res = VG_(do_syscall)(__NR_setrlimit, (UInt)resource, (UInt)rlim);
1437 if(VG_(is_kerror)(res)) res = -1;
1438 return res;
1439}
1440
1441
rjwalshf5f536f2003-11-17 17:45:00 +00001442/* Support for getdents. */
1443Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
1444{
1445 Int res;
1446 /* res = getdents( fd, dirp, count ); */
1447 res = VG_(do_syscall)(__NR_getdents, fd, (UInt)dirp, count);
1448 if (VG_(is_kerror)(res)) res = -1;
1449 return res;
1450}
1451
1452/* Support for a readlink. */
1453Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
1454{
1455 Int res;
1456 /* res = readlink( path, buf, bufsiz ); */
1457 res = VG_(do_syscall)(__NR_readlink, (UInt)path, (UInt)buf, bufsiz);
1458 if (VG_(is_kerror)(res)) res = -1;
1459 return res;
1460}
1461
sewardjde4a1d02002-03-22 01:27:54 +00001462/* You'd be amazed how many places need to know the current pid. */
1463Int VG_(getpid) ( void )
1464{
1465 Int res;
1466 /* res = getpid(); */
jsgf855d93d2003-10-13 22:26:55 +00001467 res = VG_(do_syscall)(__NR_getpid);
1468 return res;
1469}
1470
1471Int VG_(getpgrp) ( void )
1472{
1473 Int res;
1474 /* res = getpgid(); */
1475 res = VG_(do_syscall)(__NR_getpgrp);
sewardjde4a1d02002-03-22 01:27:54 +00001476 return res;
1477}
1478
sewardj4cf05692002-10-27 20:28:29 +00001479Int VG_(getppid) ( void )
1480{
1481 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001482 res = VG_(do_syscall)(__NR_getppid);
sewardj4cf05692002-10-27 20:28:29 +00001483 return res;
1484}
1485
jsgf855d93d2003-10-13 22:26:55 +00001486Int VG_(setpgid) ( Int pid, Int pgrp )
1487{
1488 return VG_(do_syscall)(__NR_setpgid, pid, pgrp);
1489}
sewardj4cf05692002-10-27 20:28:29 +00001490
nethercote60a96c52004-08-03 13:08:31 +00001491/* Walk through a colon-separated environment variable, and remove the
1492 entries which match remove_pattern. It slides everything down over
1493 the removed entries, and pads the remaining space with '\0'. It
1494 modifies the entries in place (in the client address space), but it
1495 shouldn't matter too much, since we only do this just before an
1496 execve().
1497
1498 This is also careful to mop up any excess ':'s, since empty strings
1499 delimited by ':' are considered to be '.' in a path.
1500*/
1501static void mash_colon_env(Char *varp, const Char *remove_pattern)
1502{
1503 Char *const start = varp;
1504 Char *entry_start = varp;
1505 Char *output = varp;
1506
1507 if (varp == NULL)
1508 return;
1509
1510 while(*varp) {
1511 if (*varp == ':') {
1512 Char prev;
1513 Bool match;
1514
1515 /* This is a bit subtle: we want to match against the entry
1516 we just copied, because it may have overlapped with
1517 itself, junking the original. */
1518
1519 prev = *output;
1520 *output = '\0';
1521
1522 match = VG_(string_match)(remove_pattern, entry_start);
1523
1524 *output = prev;
1525
1526 if (match) {
1527 output = entry_start;
1528 varp++; /* skip ':' after removed entry */
1529 } else
1530 entry_start = output+1; /* entry starts after ':' */
1531 }
1532
1533 *output++ = *varp++;
1534 }
1535
1536 /* match against the last entry */
1537 if (VG_(string_match)(remove_pattern, entry_start)) {
1538 output = entry_start;
1539 if (output > start) {
1540 /* remove trailing ':' */
1541 output--;
1542 vg_assert(*output == ':');
1543 }
1544 }
1545
1546 /* pad out the left-overs with '\0' */
1547 while(output < varp)
1548 *output++ = '\0';
1549}
1550
1551
1552// Removes all the Valgrind-added stuff from the passed environment. Used
1553// when starting child processes, so they don't see that added stuff.
1554void VG_(env_remove_valgrind_env_stuff)(Char** envp)
1555{
1556 Int i;
1557 Char* ld_preload_str = NULL;
1558 Char* ld_library_path_str = NULL;
1559 Char* buf;
1560
1561 // Find LD_* variables
1562 for (i = 0; envp[i] != NULL; i++) {
1563 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
1564 ld_preload_str = &envp[i][11];
1565 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
1566 ld_library_path_str = &envp[i][16];
1567 }
1568
1569 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
1570
1571 // Remove Valgrind-specific entries from LD_*.
1572 VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
1573 mash_colon_env(ld_preload_str, buf);
1574 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
1575 mash_colon_env(ld_preload_str, buf);
1576 VG_(sprintf)(buf, "%s*", VG_(libdir));
1577 mash_colon_env(ld_library_path_str, buf);
1578
1579 // Remove VALGRIND_CLO variable.
1580 VG_(env_unsetenv)(envp, VALGRINDCLO);
1581
1582 // XXX if variable becomes empty, remove it completely?
1583
1584 VG_(arena_free)(VG_AR_CORE, buf);
1585}
1586
sewardje6a25242002-04-21 22:03:07 +00001587/* Return -1 if error, else 0. NOTE does not indicate return code of
1588 child! */
1589Int VG_(system) ( Char* cmd )
1590{
1591 Int pid, res;
sewardje6a25242002-04-21 22:03:07 +00001592 if (cmd == NULL)
1593 return 1;
jsgf855d93d2003-10-13 22:26:55 +00001594 pid = VG_(do_syscall)(__NR_fork);
sewardje6a25242002-04-21 22:03:07 +00001595 if (VG_(is_kerror)(pid))
1596 return -1;
1597 if (pid == 0) {
1598 /* child */
nethercoteff9721d2004-01-26 17:10:01 +00001599 static Char** envp = NULL;
sewardje6a25242002-04-21 22:03:07 +00001600 Char* argv[4];
nethercoteff9721d2004-01-26 17:10:01 +00001601
fitzhardingeb50068f2004-02-24 23:42:55 +00001602 /* restore the DATA rlimit for the child */
1603 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1604
nethercote60a96c52004-08-03 13:08:31 +00001605 envp = env_clone(VG_(client_envp));
1606 VG_(env_remove_valgrind_env_stuff)( envp );
nethercoteff9721d2004-01-26 17:10:01 +00001607
sewardje6a25242002-04-21 22:03:07 +00001608 argv[0] = "/bin/sh";
1609 argv[1] = "-c";
1610 argv[2] = cmd;
1611 argv[3] = 0;
nethercoteff9721d2004-01-26 17:10:01 +00001612
jsgf855d93d2003-10-13 22:26:55 +00001613 (void)VG_(do_syscall)(__NR_execve,
nethercoteff9721d2004-01-26 17:10:01 +00001614 (UInt)"/bin/sh", (UInt)argv, (UInt)envp);
1615
sewardje6a25242002-04-21 22:03:07 +00001616 /* If we're still alive here, execve failed. */
fitzhardingeabab8392004-03-02 21:38:51 +00001617 VG_(exit)(1);
sewardje6a25242002-04-21 22:03:07 +00001618 } else {
1619 /* parent */
fitzhardingeabab8392004-03-02 21:38:51 +00001620 res = VG_(waitpid)(pid, NULL, 0);
sewardje6a25242002-04-21 22:03:07 +00001621 if (VG_(is_kerror)(res)) {
1622 return -1;
1623 } else {
fitzhardingeabab8392004-03-02 21:38:51 +00001624 return 0;
sewardje6a25242002-04-21 22:03:07 +00001625 }
1626 }
1627}
1628
1629
sewardjde4a1d02002-03-22 01:27:54 +00001630/* ---------------------------------------------------------------------
fitzhardinge66871692004-01-25 03:32:58 +00001631 Support for a millisecond-granularity timer.
sewardj5f07b662002-04-23 16:52:51 +00001632 ------------------------------------------------------------------ */
1633
sewardj5f07b662002-04-23 16:52:51 +00001634UInt VG_(read_millisecond_timer) ( void )
1635{
fitzhardinge426f9e62004-01-25 03:44:18 +00001636 static ULong base = 0;
fitzhardinge66871692004-01-25 03:32:58 +00001637 struct vki_timeval tv_now;
1638 ULong now;
sewardj5f07b662002-04-23 16:52:51 +00001639 Int res;
sewardj5f07b662002-04-23 16:52:51 +00001640
fitzhardinge66871692004-01-25 03:32:58 +00001641 res = VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now,
1642 (UInt)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001643
fitzhardinge66871692004-01-25 03:32:58 +00001644 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1645
1646 if (base == 0)
1647 base = now;
sewardj5f07b662002-04-23 16:52:51 +00001648
fitzhardinge66871692004-01-25 03:32:58 +00001649 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +00001650}
1651
1652
sewardj5f07b662002-04-23 16:52:51 +00001653/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001654 Primitive support for bagging memory via mmap.
1655 ------------------------------------------------------------------ */
1656
sewardje9047952002-06-05 20:28:33 +00001657void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001658{
1659 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001660 void* p;
nethercotec314eba2004-07-15 12:59:41 +00001661 p = VG_(mmap)(0, nBytes,
1662 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1663 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001664
sewardjde4a1d02002-03-22 01:27:54 +00001665 if (p != ((void*)(-1))) {
nethercotefb583e22004-09-07 23:15:37 +00001666 vg_assert((void*)VG_(valgrind_base) <= p && p <= (void*)VG_(valgrind_last));
sewardjde4a1d02002-03-22 01:27:54 +00001667 tot_alloc += (UInt)nBytes;
1668 if (0)
sewardje9047952002-06-05 20:28:33 +00001669 VG_(printf)(
1670 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1671 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001672 return p;
1673 }
sewardj7c2020b2002-09-30 22:56:03 +00001674
njn25e49d8e72002-09-23 09:36:25 +00001675 VG_(printf)("\n");
nethercote96729f82004-07-10 17:36:52 +00001676 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %d bytes failed.\n",
daywalkerb1db1232003-09-26 00:26:07 +00001677 who, nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001678 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1679 tot_alloc);
1680 VG_(printf)("\n");
nethercotee757d6e2004-07-10 16:17:52 +00001681 VG_(printf)("Sorry. You could try using a tool that uses less memory;\n");
1682 VG_(printf)("eg. addrcheck instead of memcheck.\n");
njn25e49d8e72002-09-23 09:36:25 +00001683 VG_(printf)("\n");
1684 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001685}
1686
njn25e49d8e72002-09-23 09:36:25 +00001687/* ---------------------------------------------------------------------
1688 Generally useful...
1689 ------------------------------------------------------------------ */
1690
1691Int VG_(log2) ( Int x )
1692{
1693 Int i;
1694 /* Any more than 32 and we overflow anyway... */
1695 for (i = 0; i < 32; i++) {
1696 if (1 << i == x) return i;
1697 }
1698 return -1;
1699}
1700
1701
njnd3b0c5f2003-09-30 14:43:54 +00001702// Generic shell sort. Like stdlib.h's qsort().
1703void VG_(ssort)( void* base, UInt nmemb, UInt size,
1704 Int (*compar)(void*, void*) )
1705{
1706 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1707 9841, 29524, 88573, 265720,
1708 797161, 2391484 };
1709 Int lo = 0;
1710 Int hi = nmemb-1;
1711 Int i, j, h, bigN, hp;
1712
1713 bigN = hi - lo + 1; if (bigN < 2) return;
1714 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1715 vg_assert(0 <= hp && hp < 14);
1716
1717 #define SORT \
1718 for ( ; hp >= 0; hp--) { \
1719 h = incs[hp]; \
njn92c54362003-10-15 14:00:35 +00001720 for (i = lo + h; i <= hi; i++) { \
njnd3b0c5f2003-09-30 14:43:54 +00001721 ASSIGN(v,0, a,i); \
1722 j = i; \
njn92c54362003-10-15 14:00:35 +00001723 while (COMPAR(a,(j-h), v,0) > 0) { \
njnd3b0c5f2003-09-30 14:43:54 +00001724 ASSIGN(a,j, a,(j-h)); \
1725 j = j - h; \
1726 if (j <= (lo + h - 1)) break; \
1727 } \
1728 ASSIGN(a,j, v,0); \
njnd3b0c5f2003-09-30 14:43:54 +00001729 } \
1730 }
1731
1732 // Specialised cases
1733 if (sizeof(UInt) == size) {
1734
1735 #define ASSIGN(dst, dsti, src, srci) \
1736 (dst)[(dsti)] = (src)[(srci)];
1737
1738 #define COMPAR(dst, dsti, src, srci) \
1739 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1740
1741 UInt* a = (UInt*)base;
1742 UInt v[1];
1743
1744 SORT;
1745
1746 } else if (sizeof(UShort) == size) {
1747 UShort* a = (UShort*)base;
1748 UShort v[1];
1749
1750 SORT;
1751
1752 } else if (sizeof(UChar) == size) {
1753 UChar* a = (UChar*)base;
1754 UChar v[1];
1755
1756 SORT;
1757
1758 #undef ASSIGN
1759 #undef COMPAR
1760
1761 // General case
1762 } else {
njn92c54362003-10-15 14:00:35 +00001763 char* a = base;
1764 char v[size]; // will be at least 'size' bytes
njnd3b0c5f2003-09-30 14:43:54 +00001765
1766 #define ASSIGN(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001767 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
njnd3b0c5f2003-09-30 14:43:54 +00001768
1769 #define COMPAR(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001770 compar( &dst[size*(dsti)], &src[size*(srci)] )
njnd3b0c5f2003-09-30 14:43:54 +00001771
1772 SORT;
1773
1774 #undef ASSIGN
1775 #undef COMPAR
1776 }
1777 #undef SORT
1778}
1779
sewardj73cf3bc2002-11-03 03:20:15 +00001780/* ---------------------------------------------------------------------
1781 Gruesome hackery for connecting to a logging server over the network.
1782 This is all very Linux-kernel specific.
1783 ------------------------------------------------------------------ */
1784
1785/* Various needed constants from the kernel iface (2.4),
1786 /usr/src/linux-2.4.9-31 */
1787
1788/* kernel, ./include/linux/net.h */
rjwalshf5f536f2003-11-17 17:45:00 +00001789#define SYS_SOCKET 1 /* sys_socket(2) */
1790#define SYS_CONNECT 3 /* sys_connect(2) */
1791#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
1792#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
1793#define SYS_SEND 9 /* sys_send(2) */
1794#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
sewardj73cf3bc2002-11-03 03:20:15 +00001795
1796typedef UInt __u32;
1797
1798/* Internet address. */
1799struct vki_in_addr {
1800 __u32 s_addr;
1801};
1802
1803/* kernel, include/linux/socket.h */
sewardj73cf3bc2002-11-03 03:20:15 +00001804#define AF_INET 2 /* Internet IP Protocol */
sewardj570f8902002-11-03 11:44:36 +00001805#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
sewardj73cf3bc2002-11-03 03:20:15 +00001806
1807/* kernel, ./include/asm-i386/socket.h */
1808#define SOCK_STREAM 1 /* stream (connection) socket */
1809
1810/* kernel, /usr/src/linux-2.4.9-31/linux/include/in.h */
1811/* Structure describing an Internet (IP) socket address. */
1812#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
1813struct vki_sockaddr_in {
1814 vki_sa_family_t sin_family; /* Address family */
1815 unsigned short int sin_port; /* Port number */
1816 struct vki_in_addr sin_addr; /* Internet address */
1817
1818 /* Pad to size of `struct sockaddr'. */
1819 unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
1820 sizeof(unsigned short int) -
1821 sizeof(struct vki_in_addr)];
1822};
1823
1824
1825static
1826Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1827
1828static
1829Int my_socket ( Int domain, Int type, Int protocol );
1830
1831static
1832Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1833 Int addrlen );
1834
1835static
1836UInt my_htonl ( UInt x )
1837{
1838 return
1839 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1840 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1841}
1842
1843static
1844UShort my_htons ( UShort x )
1845{
1846 return
1847 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1848}
1849
1850
1851/* The main function.
1852
1853 Supplied string contains either an ip address "192.168.0.1" or
1854 an ip address and port pair, "192.168.0.1:1500". Parse these,
1855 and return:
1856 -1 if there is a parse error
1857 -2 if no parse error, but specified host:port cannot be opened
1858 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001859 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001860*/
1861Int VG_(connect_via_socket)( UChar* str )
1862{
1863 Int sd, res;
1864 struct vki_sockaddr_in servAddr;
1865 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001866 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001867 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1868 if (!ok)
1869 return -1;
1870
1871 if (0)
1872 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1873 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1874 (ip >> 8) & 0xFF, ip & 0xFF,
1875 (UInt)port );
1876
1877 servAddr.sin_family = AF_INET;
1878 servAddr.sin_addr.s_addr = my_htonl(ip);
1879 servAddr.sin_port = my_htons(port);
1880
1881 /* create socket */
1882 sd = my_socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1883 if (sd < 0) {
1884 /* this shouldn't happen ... nevertheless */
1885 return -2;
1886 }
1887
1888 /* connect to server */
1889 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1890 sizeof(servAddr));
1891 if (res < 0) {
1892 /* connection failed */
1893 return -2;
1894 }
1895
1896 return sd;
1897}
1898
1899
1900/* Let d = one or more digits. Accept either:
1901 d.d.d.d or d.d.d.d:d
1902*/
1903Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1904{
1905# define GET_CH ((*str) ? (*str++) : 0)
1906 UInt ipa, i, j, c, any;
1907 ipa = 0;
1908 for (i = 0; i < 4; i++) {
1909 j = 0;
1910 any = 0;
1911 while (1) {
1912 c = GET_CH;
1913 if (c < '0' || c > '9') break;
1914 j = 10 * j + (int)(c - '0');
1915 any = 1;
1916 }
1917 if (any == 0 || j > 255) goto syntaxerr;
1918 ipa = (ipa << 8) + j;
1919 if (i <= 2 && c != '.') goto syntaxerr;
1920 }
1921 if (c == 0 || c == ':')
1922 *ip_addr = ipa;
1923 if (c == 0) goto ok;
1924 if (c != ':') goto syntaxerr;
1925 j = 0;
1926 any = 0;
1927 while (1) {
1928 c = GET_CH;
1929 if (c < '0' || c > '9') break;
1930 j = j * 10 + (int)(c - '0');
1931 any = 1;
1932 if (j > 65535) goto syntaxerr;
1933 }
1934 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001935 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001936 *port = (UShort)j;
1937 ok:
1938 return 1;
1939 syntaxerr:
1940 return 0;
1941# undef GET_CH
1942}
1943
1944
1945static
1946Int my_socket ( Int domain, Int type, Int protocol )
1947{
1948 Int res;
1949 UInt args[3];
1950 args[0] = domain;
1951 args[1] = type;
1952 args[2] = protocol;
jsgf855d93d2003-10-13 22:26:55 +00001953 res = VG_(do_syscall)(__NR_socketcall, SYS_SOCKET, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001954 if (VG_(is_kerror)(res))
1955 res = -1;
1956 return res;
1957}
1958
1959static
1960Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1961 Int addrlen )
1962{
1963 Int res;
1964 UInt args[3];
1965 args[0] = sockfd;
1966 args[1] = (UInt)serv_addr;
1967 args[2] = addrlen;
jsgf855d93d2003-10-13 22:26:55 +00001968 res = VG_(do_syscall)(__NR_socketcall, SYS_CONNECT, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001969 if (VG_(is_kerror)(res))
1970 res = -1;
1971 return res;
1972}
1973
1974Int VG_(write_socket)( Int sd, void *msg, Int count )
1975{
1976 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001977
1978 /* Requests not to send SIGPIPE on errors on stream oriented
1979 sockets when the other end breaks the connection. The EPIPE
1980 error is still returned. */
1981 Int flags = MSG_NOSIGNAL;
1982
sewardj73cf3bc2002-11-03 03:20:15 +00001983 Int res;
1984 UInt args[4];
1985 args[0] = sd;
1986 args[1] = (UInt)msg;
1987 args[2] = count;
1988 args[3] = flags;
jsgf855d93d2003-10-13 22:26:55 +00001989 res = VG_(do_syscall)(__NR_socketcall, SYS_SEND, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001990 if (VG_(is_kerror)(res))
1991 res = -1;
1992 return res;
1993}
1994
rjwalshf5f536f2003-11-17 17:45:00 +00001995Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1996{
1997 Int res;
1998 UInt args[3];
1999 args[0] = sd;
2000 args[1] = (UInt)name;
2001 args[2] = (UInt)namelen;
2002 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKNAME, (UInt)&args);
2003 if(VG_(is_kerror)(res))
2004 res = -1;
2005 return res;
2006}
2007
2008Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
2009{
2010 Int res;
2011 UInt args[3];
2012 args[0] = sd;
2013 args[1] = (UInt)name;
2014 args[2] = (UInt)namelen;
2015 res = VG_(do_syscall)(__NR_socketcall, SYS_GETPEERNAME, (UInt)&args);
2016 if(VG_(is_kerror)(res))
2017 res = -1;
2018 return res;
2019}
2020
2021Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
2022 Int *optlen)
2023{
2024 Int res;
2025 UInt args[5];
2026 args[0] = sd;
2027 args[1] = (UInt)level;
2028 args[2] = (UInt)optname;
2029 args[3] = (UInt)optval;
2030 args[4] = (UInt)optlen;
2031 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKOPT, (UInt)&args);
2032 if(VG_(is_kerror)(res))
2033 res = -1;
2034 return res;
2035}
2036
sewardjde4a1d02002-03-22 01:27:54 +00002037
2038/*--------------------------------------------------------------------*/
2039/*--- end vg_mylibc.c ---*/
2040/*--------------------------------------------------------------------*/