blob: 6d64cc3a6c03e14ca6baac0c2ca358aaf6819e4f [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
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{
fitzhardinge98abfc72003-12-16 02:05:15 +0000251 Addr res;
sewardjde4a1d02002-03-22 01:27:54 +0000252 UInt args[6];
fitzhardinge98abfc72003-12-16 02:05:15 +0000253
254 if (!(flags & VKI_MAP_FIXED)) {
255 start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
256 if (start == 0)
257 return (void *)-1;
258
259 flags |= VKI_MAP_FIXED;
260 }
261
sewardjde4a1d02002-03-22 01:27:54 +0000262 args[0] = (UInt)start;
263 args[1] = length;
264 args[2] = prot;
fitzhardinge98abfc72003-12-16 02:05:15 +0000265 args[3] = flags & ~(VKI_MAP_NOSYMS|VKI_MAP_CLIENT);
sewardjde4a1d02002-03-22 01:27:54 +0000266 args[4] = fd;
267 args[5] = offset;
jsgf855d93d2003-10-13 22:26:55 +0000268 res = VG_(do_syscall)(__NR_mmap, (UInt)(&(args[0])) );
fitzhardinge98abfc72003-12-16 02:05:15 +0000269
270 if (!VG_(is_kerror)(res)) {
271 UInt sf_flags = SF_MMAP;
272
273 if (flags & VKI_MAP_FIXED)
274 sf_flags |= SF_FIXED;
275 if (flags & VKI_MAP_SHARED)
276 sf_flags |= SF_SHARED;
277 if (!(flags & VKI_MAP_ANONYMOUS))
278 sf_flags |= SF_FILE;
279 if (!(flags & VKI_MAP_CLIENT))
280 sf_flags |= SF_VALGRIND;
281 if (flags & VKI_MAP_NOSYMS)
282 sf_flags |= SF_NOSYMS;
283
284 /* placeholder - caller will update flags etc if they want */
285 VG_(map_fd_segment)(res, length, prot, sf_flags, fd, offset, NULL);
286
287 if (flags & VKI_MAP_CLIENT) {
288 if (res < VG_(client_base) || res >= VG_(client_end)) {
289 VG_(munmap)((void *)res, length);
290 res = -1;
291 }
292 } else {
293 if (res < VG_(valgrind_base) || res >= VG_(valgrind_end)) {
294 VG_(munmap)((void *)res, length);
295 res = -1;
296 }
297 }
298 }
299
300
301
sewardjde4a1d02002-03-22 01:27:54 +0000302 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
303}
304
305/* Returns -1 on failure. */
306Int VG_(munmap)( void* start, Int length )
307{
jsgf855d93d2003-10-13 22:26:55 +0000308 Int res = VG_(do_syscall)(__NR_munmap, (UInt)start, (UInt)length );
fitzhardinge920d04e2003-12-20 18:19:50 +0000309 if (!VG_(is_kerror)(res))
fitzhardinge98abfc72003-12-16 02:05:15 +0000310 VG_(unmap_range)((Addr)start, length);
311 return VG_(is_kerror)(res) ? -1 : 0;
312}
313
314Int VG_(mprotect)( void *start, Int length, UInt prot )
315{
316 Int res = VG_(do_syscall)(__NR_mprotect, (UInt)start, (UInt)length, prot );
317 if (!VG_(is_kerror)(res))
318 VG_(mprotect_range)((Addr)start, length, prot);
sewardjde4a1d02002-03-22 01:27:54 +0000319 return VG_(is_kerror)(res) ? -1 : 0;
320}
321
322void VG_(exit)( Int status )
323{
jsgf855d93d2003-10-13 22:26:55 +0000324 (void)VG_(do_syscall)(__NR_exit_group, (UInt)status );
325 (void)VG_(do_syscall)(__NR_exit, (UInt)status );
sewardjde4a1d02002-03-22 01:27:54 +0000326 /* Why are we still alive here? */
327 /*NOTREACHED*/
jsgf855d93d2003-10-13 22:26:55 +0000328 *(volatile Int *)0 = 'x';
sewardjde4a1d02002-03-22 01:27:54 +0000329 vg_assert(2+2 == 5);
330}
331
sewardj2e93c502002-04-12 11:12:52 +0000332/* Returns -1 on error. */
333Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
334{
jsgf855d93d2003-10-13 22:26:55 +0000335 Int res = VG_(do_syscall)(__NR_fcntl, fd, cmd, arg);
sewardj2e93c502002-04-12 11:12:52 +0000336 return VG_(is_kerror)(res) ? -1 : res;
337}
338
339/* Returns -1 on error. */
340Int VG_(select)( Int n,
341 vki_fd_set* readfds,
342 vki_fd_set* writefds,
343 vki_fd_set* exceptfds,
344 struct vki_timeval * timeout )
345{
346 Int res;
347 UInt args[5];
348 args[0] = n;
349 args[1] = (UInt)readfds;
350 args[2] = (UInt)writefds;
351 args[3] = (UInt)exceptfds;
352 args[4] = (UInt)timeout;
jsgf855d93d2003-10-13 22:26:55 +0000353 res = VG_(do_syscall)(__NR_select, (UInt)(&(args[0])) );
sewardj2e93c502002-04-12 11:12:52 +0000354 return VG_(is_kerror)(res) ? -1 : res;
sewardj2e93c502002-04-12 11:12:52 +0000355}
356
jsgf855d93d2003-10-13 22:26:55 +0000357Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
358{
359 Int res = VG_(do_syscall)(__NR_poll, ufds, nfds, timeout);
360
361 return res;
362}
363
sewardj5f07b662002-04-23 16:52:51 +0000364/* Returns -1 on error, 0 if ok, 1 if interrupted. */
sewardj2e93c502002-04-12 11:12:52 +0000365Int VG_(nanosleep)( const struct vki_timespec *req,
366 struct vki_timespec *rem )
367{
368 Int res;
jsgf855d93d2003-10-13 22:26:55 +0000369 res = VG_(do_syscall)(__NR_nanosleep, (UInt)req, (UInt)rem);
sewardj2e93c502002-04-12 11:12:52 +0000370 if (res == -VKI_EINVAL) return -1;
sewardj5f07b662002-04-23 16:52:51 +0000371 if (res == -VKI_EINTR) return 1;
sewardj2e93c502002-04-12 11:12:52 +0000372 return 0;
373}
374
sewardjb3586202002-05-09 17:38:13 +0000375void* VG_(brk) ( void* end_data_segment )
376{
377 Int res;
jsgf855d93d2003-10-13 22:26:55 +0000378 res = VG_(do_syscall)(__NR_brk, (UInt)end_data_segment);
sewardjb3586202002-05-09 17:38:13 +0000379 return (void*)( VG_(is_kerror)(res) ? -1 : res );
380}
381
sewardj2e93c502002-04-12 11:12:52 +0000382
sewardjde4a1d02002-03-22 01:27:54 +0000383/* ---------------------------------------------------------------------
384 printf implementation. The key function, vg_vprintf(), emits chars
385 into a caller-supplied function. Distantly derived from:
386
387 vprintf replacement for Checker.
388 Copyright 1993, 1994, 1995 Tristan Gingold
389 Written September 1993 Tristan Gingold
390 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
391
392 (Checker itself was GPL'd.)
393 ------------------------------------------------------------------ */
394
395
396/* Some flags. */
397#define VG_MSG_SIGNED 1 /* The value is signed. */
398#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
399#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
sewardj78e3cd92002-10-22 04:45:48 +0000400#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
njn607adfc2003-09-30 14:15:44 +0000401#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
sewardjde4a1d02002-03-22 01:27:54 +0000402
403/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000404static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000405myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
406 Bool capitalise )
407{
408# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000409 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000410 Int i, extra;
411 Int len = VG_(strlen)(str);
412
413 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000414 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000415 for (i = 0; i < len; i++)
416 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000417 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000418 }
419
420 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000421 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000422 for (i = 0; i < width; i++)
423 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000424 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000425 }
426
427 extra = width - len;
428 if (flags & VG_MSG_LJUSTIFY) {
sewardj78e3cd92002-10-22 04:45:48 +0000429 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000430 for (i = 0; i < extra; i++)
431 send(' ');
432 }
sewardj78e3cd92002-10-22 04:45:48 +0000433 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000434 for (i = 0; i < len; i++)
435 send(MAYBE_TOUPPER(str[i]));
436 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000437 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000438 for (i = 0; i < extra; i++)
439 send(' ');
440 }
441
442# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000443
444 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000445}
446
447/* Write P into the buffer according to these args:
448 * If SIGN is true, p is a signed.
449 * BASE is the base.
450 * If WITH_ZERO is true, '0' must be added.
451 * WIDTH is the width of the field.
452 */
sewardj78e3cd92002-10-22 04:45:48 +0000453static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000454myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
455{
456 Char buf[40];
457 Int ind = 0;
njn607adfc2003-09-30 14:15:44 +0000458 Int i, nc = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000459 Bool neg = False;
460 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000461 UInt ret = 0;
462
sewardjde4a1d02002-03-22 01:27:54 +0000463 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000464 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000465
466 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
467 p = - (Long)p;
468 neg = True;
469 }
470
471 if (p == 0)
472 buf[ind++] = '0';
473 else {
474 while (p > 0) {
njn607adfc2003-09-30 14:15:44 +0000475 if (flags & VG_MSG_COMMA && 10 == base &&
476 0 == (ind-nc) % 3 && 0 != ind)
477 {
478 buf[ind++] = ',';
479 nc++;
480 }
sewardjde4a1d02002-03-22 01:27:54 +0000481 buf[ind++] = digits[p % base];
482 p /= base;
njn607adfc2003-09-30 14:15:44 +0000483 }
sewardjde4a1d02002-03-22 01:27:54 +0000484 }
485
486 if (neg)
487 buf[ind++] = '-';
488
489 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
490 for(; ind < width; ind++) {
491 vg_assert(ind < 39);
492 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
493 }
494 }
495
496 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000497 ret += ind;
njn607adfc2003-09-30 14:15:44 +0000498 for (i = ind -1; i >= 0; i--) {
sewardjde4a1d02002-03-22 01:27:54 +0000499 send(buf[i]);
njn607adfc2003-09-30 14:15:44 +0000500 }
sewardjde4a1d02002-03-22 01:27:54 +0000501 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000502 for(; ind < width; ind++) {
503 ret++;
njn607adfc2003-09-30 14:15:44 +0000504 send(' '); // Never pad with zeroes on RHS -- changes the value!
sewardj78e3cd92002-10-22 04:45:48 +0000505 }
sewardjde4a1d02002-03-22 01:27:54 +0000506 }
sewardj78e3cd92002-10-22 04:45:48 +0000507 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000508}
509
510
511/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000512UInt
sewardjde4a1d02002-03-22 01:27:54 +0000513VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
514{
sewardj78e3cd92002-10-22 04:45:48 +0000515 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000516 int i;
517 int flags;
518 int width;
519 Bool is_long;
520
521 /* We assume that vargs has already been initialised by the
522 caller, using va_start, and that the caller will similarly
523 clean up with va_end.
524 */
525
526 for (i = 0; format[i] != 0; i++) {
527 if (format[i] != '%') {
528 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000529 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000530 continue;
531 }
532 i++;
533 /* A '%' has been found. Ignore a trailing %. */
534 if (format[i] == 0)
535 break;
536 if (format[i] == '%') {
537 /* `%%' is replaced by `%'. */
538 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000539 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000540 continue;
541 }
542 flags = 0;
543 is_long = False;
544 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000545 if (format[i] == '(') {
546 flags |= VG_MSG_PAREN;
547 i++;
548 }
njn607adfc2003-09-30 14:15:44 +0000549 /* If ',' follows '%', commas will be inserted. */
550 if (format[i] == ',') {
551 flags |= VG_MSG_COMMA;
552 i++;
553 }
sewardjde4a1d02002-03-22 01:27:54 +0000554 /* If '-' follows '%', justify on the left. */
555 if (format[i] == '-') {
556 flags |= VG_MSG_LJUSTIFY;
557 i++;
558 }
559 /* If '0' follows '%', pads will be inserted. */
560 if (format[i] == '0') {
561 flags |= VG_MSG_ZJUSTIFY;
562 i++;
563 }
564 /* Compute the field length. */
565 while (format[i] >= '0' && format[i] <= '9') {
566 width *= 10;
567 width += format[i++] - '0';
568 }
569 while (format[i] == 'l') {
570 i++;
571 is_long = True;
572 }
573
574 switch (format[i]) {
575 case 'd': /* %d */
576 flags |= VG_MSG_SIGNED;
577 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000578 ret += myvprintf_int64(send, flags, 10, width,
579 (ULong)(va_arg (vargs, Long)));
sewardjde4a1d02002-03-22 01:27:54 +0000580 else
sewardj78e3cd92002-10-22 04:45:48 +0000581 ret += myvprintf_int64(send, flags, 10, width,
582 (ULong)(va_arg (vargs, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000583 break;
584 case 'u': /* %u */
585 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000586 ret += myvprintf_int64(send, flags, 10, width,
587 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000588 else
sewardj78e3cd92002-10-22 04:45:48 +0000589 ret += myvprintf_int64(send, flags, 10, width,
590 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000591 break;
592 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000593 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000594 send('0');
595 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000596 ret += myvprintf_int64(send, flags, 16, width,
597 (ULong)((UInt)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000598 break;
599 case 'x': /* %x */
600 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000601 ret += myvprintf_int64(send, flags, 16, width,
602 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000603 else
sewardj78e3cd92002-10-22 04:45:48 +0000604 ret += myvprintf_int64(send, flags, 16, width,
605 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000606 break;
607 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000608 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000609 send(va_arg (vargs, int));
610 break;
611 case 's': case 'S': { /* %s */
612 char *str = va_arg (vargs, char *);
613 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000614 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000615 break;
sewardj78e3cd92002-10-22 04:45:48 +0000616 }
617 case 'y': { /* %y - print symbol */
618 Char buf[100];
619 Char *cp = buf;
620 Addr a = va_arg(vargs, Addr);
621
622 if (flags & VG_MSG_PAREN)
623 *cp++ = '(';
sewardj6e008cb2002-12-15 13:11:39 +0000624 if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
sewardj78e3cd92002-10-22 04:45:48 +0000625 if (flags & VG_MSG_PAREN) {
626 cp += VG_(strlen)(cp);
627 *cp++ = ')';
628 *cp = '\0';
629 }
630 ret += myvprintf_str(send, flags, width, buf, 0);
631 }
632
633 break;
634 }
sewardjde4a1d02002-03-22 01:27:54 +0000635 default:
636 break;
637 }
638 }
sewardj78e3cd92002-10-22 04:45:48 +0000639 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000640}
641
642
643/* A general replacement for printf(). Note that only low-level
644 debugging info should be sent via here. The official route is to
645 to use vg_message(). This interface is deprecated.
646*/
647static char myprintf_buf[100];
648static int n_myprintf_buf;
649
650static void add_to_myprintf_buf ( Char c )
651{
652 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
sewardj73cf3bc2002-11-03 03:20:15 +0000653 if (VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000654 VG_(send_bytes_to_logging_sink)(
655 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000656 }
sewardjde4a1d02002-03-22 01:27:54 +0000657 n_myprintf_buf = 0;
658 myprintf_buf[n_myprintf_buf] = 0;
659 }
660 myprintf_buf[n_myprintf_buf++] = c;
661 myprintf_buf[n_myprintf_buf] = 0;
662}
663
sewardj78e3cd92002-10-22 04:45:48 +0000664UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000665{
sewardj78e3cd92002-10-22 04:45:48 +0000666 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000667 va_list vargs;
668 va_start(vargs,format);
669
670 n_myprintf_buf = 0;
671 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000672 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000673
sewardj73cf3bc2002-11-03 03:20:15 +0000674 if (n_myprintf_buf > 0 && VG_(clo_logfile_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000675 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000676 }
sewardjde4a1d02002-03-22 01:27:54 +0000677
678 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000679
680 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000681}
682
683
684/* A general replacement for sprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000685UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000686{
sewardj05bcdcb2003-05-18 10:05:38 +0000687 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000688 va_list vargs;
sewardj1771e172002-11-13 22:06:35 +0000689 Char *ptr = buf;
690 static void add_to_vg_sprintf_buf ( Char c )
691 {
692 *ptr++ = c;
693 }
694
sewardjde4a1d02002-03-22 01:27:54 +0000695 va_start(vargs,format);
696
sewardj78e3cd92002-10-22 04:45:48 +0000697 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000698 add_to_vg_sprintf_buf(0);
699
700 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000701
702 vg_assert(VG_(strlen)(buf) == ret);
703 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000704}
705
706
707/* ---------------------------------------------------------------------
708 Misc str* functions.
709 ------------------------------------------------------------------ */
710
711Bool VG_(isspace) ( Char c )
712{
713 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
714}
715
njn7cf0bd32002-06-08 13:36:03 +0000716Bool VG_(isdigit) ( Char c )
717{
718 return (c >= '0' && c <= '9');
719}
sewardjde4a1d02002-03-22 01:27:54 +0000720
721Int VG_(strlen) ( const Char* str )
722{
723 Int i = 0;
724 while (str[i] != 0) i++;
725 return i;
726}
727
728
729Long VG_(atoll) ( Char* str )
730{
731 Bool neg = False;
732 Long n = 0;
733 if (*str == '-') { str++; neg = True; };
734 while (*str >= '0' && *str <= '9') {
735 n = 10*n + (Long)(*str - '0');
736 str++;
737 }
738 if (neg) n = -n;
739 return n;
740}
741
742
njn25e49d8e72002-09-23 09:36:25 +0000743Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000744{
745 Bool neg = False;
746 Long n = 0;
747 if (*str == '-') { str++; neg = True; };
748 while (True) {
749 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000750 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000751 }
752 else
njn25e49d8e72002-09-23 09:36:25 +0000753 if (*str >= 'A' && *str <= 'F') {
754 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000755 }
756 else
njn25e49d8e72002-09-23 09:36:25 +0000757 if (*str >= 'a' && *str <= 'f') {
758 n = 16*n + (Long)((*str - 'a') + 10);
759 }
760 else {
761 break;
762 }
763 str++;
764 }
765 if (neg) n = -n;
766 return n;
767}
768
769Long VG_(atoll36) ( UInt base, Char* str )
770{
771 Bool neg = False;
772 Long n = 0;
773 vg_assert(base >= 2 && base <= 36);
774 if (*str == '-') { str++; neg = True; };
775 while (True) {
sewardj05bcdcb2003-05-18 10:05:38 +0000776 if (*str >= '0'
777 && *str <= (Char)('9' - (10 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000778 n = base*n + (Long)(*str - '0');
779 }
780 else
sewardj05bcdcb2003-05-18 10:05:38 +0000781 if (base > 10 && *str >= 'A'
782 && *str <= (Char)('Z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000783 n = base*n + (Long)((*str - 'A') + 10);
784 }
785 else
sewardj05bcdcb2003-05-18 10:05:38 +0000786 if (base > 10 && *str >= 'a'
787 && *str <= (Char)('z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000788 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000789 }
790 else {
791 break;
792 }
793 str++;
794 }
795 if (neg) n = -n;
796 return n;
797}
798
799
sewardjde4a1d02002-03-22 01:27:54 +0000800Char* VG_(strcat) ( Char* dest, const Char* src )
801{
802 Char* dest_orig = dest;
803 while (*dest) dest++;
804 while (*src) *dest++ = *src++;
805 *dest = 0;
806 return dest_orig;
807}
808
809
810Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
811{
812 Char* dest_orig = dest;
813 while (*dest) dest++;
814 while (*src && n > 0) { *dest++ = *src++; n--; }
815 *dest = 0;
816 return dest_orig;
817}
818
819
820Char* VG_(strpbrk) ( const Char* s, const Char* accept )
821{
822 const Char* a;
823 while (*s) {
824 a = accept;
825 while (*a)
826 if (*a++ == *s)
827 return (Char *) s;
828 s++;
829 }
830 return NULL;
831}
832
833
834Char* VG_(strcpy) ( Char* dest, const Char* src )
835{
836 Char* dest_orig = dest;
837 while (*src) *dest++ = *src++;
838 *dest = 0;
839 return dest_orig;
840}
841
842
843/* Copy bytes, not overrunning the end of dest and always ensuring
844 zero termination. */
845void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
846{
847 Int i;
848 vg_assert(ndest > 0);
849 i = 0;
850 dest[i] = 0;
851 while (True) {
852 if (src[i] == 0) return;
853 if (i >= ndest-1) return;
854 dest[i] = src[i];
855 i++;
856 dest[i] = 0;
857 }
858}
859
860
njn25e49d8e72002-09-23 09:36:25 +0000861Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000862{
njn25e49d8e72002-09-23 09:36:25 +0000863 Int i = 0;
864 while (True) {
865 if (i >= ndest) return dest; /* reached limit */
866 dest[i] = src[i];
867 if (src[i++] == 0) {
868 /* reached NUL; pad rest with zeroes as required */
869 while (i < ndest) dest[i++] = 0;
870 return dest;
871 }
872 }
sewardjde4a1d02002-03-22 01:27:54 +0000873}
874
875
876Int VG_(strcmp) ( const Char* s1, const Char* s2 )
877{
878 while (True) {
879 if (*s1 == 0 && *s2 == 0) return 0;
880 if (*s1 == 0) return -1;
881 if (*s2 == 0) return 1;
882
883 if (*(UChar*)s1 < *(UChar*)s2) return -1;
884 if (*(UChar*)s1 > *(UChar*)s2) return 1;
885
886 s1++; s2++;
887 }
888}
889
890
891Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
892{
893 while (True) {
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++;
902 }
903}
904
905
906Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
907{
908 Int n = 0;
909 while (True) {
910 if (n >= nmax) return 0;
911 if (*s1 == 0 && *s2 == 0) return 0;
912 if (*s1 == 0) return -1;
913 if (*s2 == 0) return 1;
914
915 if (*(UChar*)s1 < *(UChar*)s2) return -1;
916 if (*(UChar*)s1 > *(UChar*)s2) return 1;
917
918 s1++; s2++; n++;
919 }
920}
921
922
923Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
924{
925 Int n = 0;
926 while (True) {
927 if (n >= nmax) return 0;
928 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
929 if (VG_(isspace)(*s1)) return -1;
930 if (VG_(isspace)(*s2)) return 1;
931
932 if (*(UChar*)s1 < *(UChar*)s2) return -1;
933 if (*(UChar*)s1 > *(UChar*)s2) return 1;
934
935 s1++; s2++; n++;
936 }
937}
938
939
940Char* VG_(strstr) ( const Char* haystack, Char* needle )
941{
sewardj3984b852002-05-12 03:00:17 +0000942 Int n;
943 if (haystack == NULL)
944 return NULL;
945 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000946 while (True) {
947 if (haystack[0] == 0)
948 return NULL;
949 if (VG_(strncmp)(haystack, needle, n) == 0)
950 return (Char*)haystack;
951 haystack++;
952 }
953}
954
955
956Char* VG_(strchr) ( const Char* s, Char c )
957{
958 while (True) {
959 if (*s == c) return (Char*)s;
960 if (*s == 0) return NULL;
961 s++;
962 }
963}
964
965
sewardj7ab2aca2002-10-20 19:40:32 +0000966void* VG_(memcpy) ( void *dest, const void *src, Int sz )
967{
968 const Char *s = (const Char *)src;
969 Char *d = (Char *)dest;
970 vg_assert(sz >= 0);
971
972 while (sz--)
973 *d++ = *s++;
974
975 return dest;
976}
977
978
979void* VG_(memset) ( void *dest, Int c, Int sz )
980{
981 Char *d = (Char *)dest;
982 vg_assert(sz >= 0);
983
984 while (sz--)
985 *d++ = c;
986
987 return dest;
988}
989
njn6d68e792003-02-24 10:49:08 +0000990Int VG_(memcmp) ( const void* s1, const void* s2, Int n )
991{
992 Int res;
njnfa4690b2003-02-24 21:43:05 +0000993 UChar a0;
994 UChar b0;
njn6d68e792003-02-24 10:49:08 +0000995 vg_assert(n >= 0);
996
997 while (n != 0) {
njnfa4690b2003-02-24 21:43:05 +0000998 a0 = ((UChar *) s1)[0];
999 b0 = ((UChar *) s2)[0];
njn6d68e792003-02-24 10:49:08 +00001000 s1 += 1;
1001 s2 += 1;
1002 res = a0 - b0;
1003 if (res != 0)
1004 return res;
1005 n -= 1;
1006 }
1007 return 0;
1008}
sewardj7ab2aca2002-10-20 19:40:32 +00001009
sewardjde4a1d02002-03-22 01:27:54 +00001010Char VG_(toupper) ( Char c )
1011{
1012 if (c >= 'a' && c <= 'z')
1013 return c + ('A' - 'a');
1014 else
1015 return c;
1016}
1017
1018
njn25e49d8e72002-09-23 09:36:25 +00001019/* Inline just for the wrapper VG_(strdup) below */
1020__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +00001021{
njn25e49d8e72002-09-23 09:36:25 +00001022 Int i;
fitzhardingea7728472003-12-16 01:48:38 +00001023 Int len;
1024 Char* res;
1025
1026 if (s == NULL)
1027 return NULL;
1028
1029 len = VG_(strlen)(s) + 1;
1030 res = VG_(arena_malloc) (aid, len);
1031
njn25e49d8e72002-09-23 09:36:25 +00001032 for (i = 0; i < len; i++)
1033 res[i] = s[i];
1034 return res;
sewardjde4a1d02002-03-22 01:27:54 +00001035}
1036
nethercote7cc9c232004-01-21 15:08:04 +00001037/* Wrapper to avoid exposing tools to ArenaId's */
njn25e49d8e72002-09-23 09:36:25 +00001038Char* VG_(strdup) ( const Char* s )
1039{
nethercote60f5b822004-01-26 17:24:42 +00001040 return VG_(arena_strdup) ( VG_AR_TOOL, s );
njn25e49d8e72002-09-23 09:36:25 +00001041}
sewardjde4a1d02002-03-22 01:27:54 +00001042
1043/* ---------------------------------------------------------------------
1044 A simple string matching routine, purloined from Hugs98.
1045 `*' matches any sequence of zero or more characters
1046 `?' matches any single character exactly
1047 `\c' matches the character c only (ignoring special chars)
1048 c matches the character c only
1049 ------------------------------------------------------------------ */
1050
1051/* Keep track of recursion depth. */
1052static Int recDepth;
1053
fitzhardinge98abfc72003-12-16 02:05:15 +00001054static Bool string_match_wrk ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001055{
sewardje54b69d2003-07-06 01:14:42 +00001056 vg_assert(recDepth >= 0 && recDepth < 500);
sewardjde4a1d02002-03-22 01:27:54 +00001057 recDepth++;
1058 for (;;) {
1059 switch (*pat) {
1060 case '\0' : return (*str=='\0');
1061 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001062 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001063 recDepth--;
1064 return True;
1065 }
1066 } while (*str++);
1067 recDepth--;
1068 return False;
1069 case '?' : if (*str++=='\0') {
1070 recDepth--;
1071 return False;
1072 }
1073 pat++;
1074 break;
1075 case '\\' : if (*++pat == '\0') {
1076 recDepth--;
1077 return False; /* spurious trailing \ in pattern */
1078 }
1079 /* falls through to ... */
1080 default : if (*pat++ != *str++) {
1081 recDepth--;
1082 return False;
1083 }
1084 break;
1085 }
1086 }
1087}
1088
fitzhardinge98abfc72003-12-16 02:05:15 +00001089Bool VG_(string_match) ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001090{
1091 Bool b;
1092 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001093 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001094 /*
1095 VG_(printf)("%s %s %s\n",
1096 b?"TRUE ":"FALSE", pat, str);
1097 */
1098 return b;
1099}
1100
1101
1102/* ---------------------------------------------------------------------
1103 Assertery.
1104 ------------------------------------------------------------------ */
1105
jsgf855d93d2003-10-13 22:26:55 +00001106/* Fake up an ExeContext which is of our actual real CPU state, so we
1107 can print a stack trace. This isn't terribly useful in the case
1108 where we were killed by a signal, since we just get a backtrace
1109 into the signal handler. Also, it could be somewhat risky if we
1110 actully got the panic/exception within the execontext/stack
1111 dump/symtab code. But it's better than nothing. */
1112static inline ExeContext *get_real_execontext(Addr ret)
1113{
1114 ExeContext *ec;
fitzhardingea09a1b52003-11-07 23:09:48 +00001115 Addr esp, ebp;
jsgf855d93d2003-10-13 22:26:55 +00001116 Addr stacktop;
jsgf855d93d2003-10-13 22:26:55 +00001117
fitzhardingea09a1b52003-11-07 23:09:48 +00001118 asm("movl %%ebp, %0; movl %%esp, %1" : "=r" (ebp), "=r" (esp));
fitzhardinge98abfc72003-12-16 02:05:15 +00001119 stacktop = VG_(valgrind_end);
jsgf855d93d2003-10-13 22:26:55 +00001120 if (esp >= (Addr)&VG_(sigstack)[0] && esp < (Addr)&VG_(sigstack)[VG_STACK_SIZE_W])
1121 stacktop = (Addr)&VG_(sigstack)[VG_STACK_SIZE_W];
1122
1123 ec = VG_(get_ExeContext2)(ret, ebp, esp, stacktop);
1124
1125 return ec;
1126}
1127
njne427a662002-10-02 11:08:25 +00001128__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001129static void report_and_quit ( const Char* report )
njne427a662002-10-02 11:08:25 +00001130{
jsgf855d93d2003-10-13 22:26:55 +00001131 ExeContext *ec = get_real_execontext((Addr)__builtin_return_address(0));
1132 VG_(pp_ExeContext)(ec);
1133
njne427a662002-10-02 11:08:25 +00001134 VG_(pp_sched_status)();
sewardj366ee1e2003-04-26 22:36:42 +00001135 VG_(printf)("\n");
1136 VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
1137 VG_(printf)("It contains workarounds to several common problems.\n");
1138 VG_(printf)("\n");
1139 VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
1140 report);
1141 VG_(printf)("In the bug report, send all the above text, the valgrind\n");
sewardj96330bd2003-04-27 23:46:21 +00001142 VG_(printf)("version, and what Linux distro you are using. Thanks.\n\n");
njne427a662002-10-02 11:08:25 +00001143 VG_(shutdown_logging)();
1144 VG_(exit)(1);
1145}
1146
1147__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001148static void assert_fail ( const Char* expr, const Char* name, const Char* report,
1149 const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001150{
sewardj018f7622002-05-15 21:13:39 +00001151 static Bool entered = False;
1152 if (entered)
1153 VG_(exit)(2);
1154 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001155 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001156 name, file, line, fn, expr );
1157 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001158}
1159
daywalker3222e0a2003-09-18 01:39:50 +00001160void VG_(skin_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001161{
njnd04b7c62002-10-03 14:05:52 +00001162 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001163 file, line, fn);
1164}
1165
daywalker3222e0a2003-09-18 01:39:50 +00001166void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
njne427a662002-10-02 11:08:25 +00001167{
nethercote421281e2003-11-20 16:20:55 +00001168 assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn);
njne427a662002-10-02 11:08:25 +00001169}
1170
1171__attribute__ ((noreturn))
1172static void panic ( Char* name, Char* report, Char* str )
1173{
1174 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001175 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
njne427a662002-10-02 11:08:25 +00001176 report_and_quit(report);
sewardjde4a1d02002-03-22 01:27:54 +00001177}
1178
njne427a662002-10-02 11:08:25 +00001179void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001180{
nethercote421281e2003-11-20 16:20:55 +00001181 panic("valgrind", VG_BUGS_TO, str);
njn25e49d8e72002-09-23 09:36:25 +00001182}
1183
njne427a662002-10-02 11:08:25 +00001184void VG_(skin_panic) ( Char* str )
1185{
njnd04b7c62002-10-03 14:05:52 +00001186 panic(VG_(details).name, VG_(details).bug_reports_to, str);
njne427a662002-10-02 11:08:25 +00001187}
sewardjde4a1d02002-03-22 01:27:54 +00001188
njn13f02932003-04-30 20:23:58 +00001189
sewardjde4a1d02002-03-22 01:27:54 +00001190/* ---------------------------------------------------------------------
1191 Primitive support for reading files.
1192 ------------------------------------------------------------------ */
1193
jsgf855d93d2003-10-13 22:26:55 +00001194static inline Bool fd_exists(Int fd)
1195{
1196 struct vki_stat st;
1197
1198 return VG_(fstat)(fd, &st) == 0;
1199}
1200
1201/* Move an fd into the Valgrind-safe range */
1202Int VG_(safe_fd)(Int oldfd)
1203{
1204 Int newfd;
1205
fitzhardingeb791a192003-12-18 07:22:44 +00001206 vg_assert(VG_(max_fd) != -1);
1207
fitzhardingef0046f22003-12-18 02:39:22 +00001208 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001209 if (newfd != -1)
1210 VG_(close)(oldfd);
1211
1212 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
1213
fitzhardingef0046f22003-12-18 02:39:22 +00001214 vg_assert(newfd > VG_(max_fd));
jsgf855d93d2003-10-13 22:26:55 +00001215 return newfd;
1216}
1217
1218
1219
sewardjde4a1d02002-03-22 01:27:54 +00001220/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001221Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1222{
sewardjde4a1d02002-03-22 01:27:54 +00001223 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001224
njn25e49d8e72002-09-23 09:36:25 +00001225 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001226 /* This gets a segmentation fault if pathname isn't a valid file.
1227 I don't know why. It seems like the call to open is getting
1228 intercepted and messed with by glibc ... */
1229 /* fd = open( pathname, O_RDONLY ); */
1230 /* ... so we go direct to the horse's mouth, which seems to work
1231 ok: */
jsgf855d93d2003-10-13 22:26:55 +00001232 fd = VG_(do_syscall)(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001233 /* VG_(printf)("result = %d\n", fd); */
jsgff3c3f1a2003-10-14 22:13:28 +00001234 /* return -ve error code */
njn4f9c9342002-04-29 16:03:24 +00001235 return fd;
1236}
sewardjde4a1d02002-03-22 01:27:54 +00001237
jsgf855d93d2003-10-13 22:26:55 +00001238Int VG_(pipe) ( Int fd[2] )
1239{
1240 Int ret = VG_(do_syscall)(__NR_pipe, fd);
1241 return VG_(is_kerror)(ret) ? -1 : 0;
1242}
1243
sewardjde4a1d02002-03-22 01:27:54 +00001244void VG_(close) ( Int fd )
1245{
jsgf855d93d2003-10-13 22:26:55 +00001246 VG_(do_syscall)(__NR_close, fd);
sewardjde4a1d02002-03-22 01:27:54 +00001247}
1248
1249
1250Int VG_(read) ( Int fd, void* buf, Int count)
1251{
1252 Int res;
1253 /* res = read( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001254 res = VG_(do_syscall)(__NR_read, fd, (UInt)buf, count);
1255 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001256 return res;
1257}
1258
jsgf855d93d2003-10-13 22:26:55 +00001259Int VG_(write) ( Int fd, const void* buf, Int count)
sewardjde4a1d02002-03-22 01:27:54 +00001260{
1261 Int res;
1262 /* res = write( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001263 res = VG_(do_syscall)(__NR_write, fd, (UInt)buf, count);
1264 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001265 return res;
1266}
1267
rjwalshf5f536f2003-11-17 17:45:00 +00001268Int VG_(lseek) ( Int fd, Long offset, Int whence)
1269{
1270 Int res;
1271 /* res = lseek( fd, offset, whence ); */
1272 res = VG_(do_syscall)(__NR_lseek, fd, (UInt)offset, whence);
1273 if (VG_(is_kerror)(res)) res = -1;
1274 return res;
1275}
1276
sewardjb3586202002-05-09 17:38:13 +00001277Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1278{
1279 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001280 res = VG_(do_syscall)(__NR_stat, (UInt)file_name, (UInt)buf);
fitzhardingee1c06d82003-10-30 07:21:44 +00001281 return res; /* return -ve error */
njn41557122002-10-14 09:25:37 +00001282}
1283
jsgf855d93d2003-10-13 22:26:55 +00001284Int VG_(fstat) ( Int fd, struct vki_stat* buf )
1285{
1286 Int res;
1287 res = VG_(do_syscall)(__NR_fstat, (UInt)fd, (UInt)buf);
1288 return VG_(is_kerror)(res) ? (-1) : 0;
1289}
1290
1291Int VG_(dup2) ( Int oldfd, Int newfd )
1292{
1293 Int res;
1294 res = VG_(do_syscall)(__NR_dup2, (UInt)oldfd, (UInt)newfd);
1295 return VG_(is_kerror)(res) ? (-1) : res;
1296}
1297
njn41557122002-10-14 09:25:37 +00001298Int VG_(rename) ( Char* old_name, Char* new_name )
1299{
1300 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001301 res = VG_(do_syscall)(__NR_rename, (UInt)old_name, (UInt)new_name);
njn41557122002-10-14 09:25:37 +00001302 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001303}
1304
njn4aca2d22002-10-04 10:29:38 +00001305Int VG_(unlink) ( Char* file_name )
1306{
1307 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001308 res = VG_(do_syscall)(__NR_unlink, (UInt)file_name);
njn41557122002-10-14 09:25:37 +00001309 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001310}
1311
njn13f02932003-04-30 20:23:58 +00001312/* Nb: we do not allow the Linux extension which malloc()s memory for the
1313 buffer if buf==NULL, because we don't want Linux calling malloc() */
1314Char* VG_(getcwd) ( Char* buf, Int size )
1315{
1316 Int res;
1317 vg_assert(buf != NULL);
jsgf855d93d2003-10-13 22:26:55 +00001318 res = VG_(do_syscall)(__NR_getcwd, (UInt)buf, (UInt)size);
njn13f02932003-04-30 20:23:58 +00001319 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1320}
1321
njn99ccf082003-09-30 13:51:23 +00001322/* Alternative version that does allocate the memory. Easier to use. */
1323Bool VG_(getcwd_alloc) ( Char** out )
1324{
1325 UInt size = 4;
1326
1327 *out = NULL;
1328 while (True) {
1329 *out = VG_(malloc)(size);
1330 if (NULL == VG_(getcwd)(*out, size)) {
1331 VG_(free)(*out);
1332 if (size > 65535)
1333 return False;
1334 size *= 2;
1335 } else {
1336 return True;
1337 }
1338 }
1339}
1340
njn13f02932003-04-30 20:23:58 +00001341
1342/* ---------------------------------------------------------------------
1343 Misc functions looking for a proper home.
1344 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001345
nethercoteff9721d2004-01-26 17:10:01 +00001346/* clone the environment */
1347Char **VG_(env_clone) ( Char **oldenv )
1348{
1349 Char **oldenvp;
1350 Char **newenvp;
1351 Char **newenv;
1352 Int envlen;
1353
1354 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
1355
1356 envlen = oldenvp - oldenv + 1;
1357
1358 newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1359
1360 oldenvp = oldenv;
1361 newenvp = newenv;
1362
1363 while (oldenvp && *oldenvp) {
1364 *newenvp++ = *oldenvp++;
1365 }
1366
1367 *newenvp = *oldenvp;
1368
1369 return newenv;
1370}
1371
fitzhardinge98abfc72003-12-16 02:05:15 +00001372void VG_(env_unsetenv) ( Char **env, const Char *varname )
1373{
1374 Char **from;
1375 Char **to = NULL;
1376 Int len = VG_(strlen)(varname);
1377
1378 for(from = to = env; from && *from; from++) {
1379 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
1380 *to = *from;
1381 to++;
1382 }
1383 }
1384 *to = *from;
1385}
1386
1387/* set the environment; returns the old env if a new one was allocated */
1388Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
1389{
1390 Char **env = (*envp);
1391 Char **cpp;
1392 Int len = VG_(strlen)(varname);
1393 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, len + VG_(strlen)(val) + 2);
1394 Char **oldenv = NULL;
1395
1396 VG_(sprintf)(valstr, "%s=%s", varname, val);
1397
1398 for(cpp = env; cpp && *cpp; cpp++) {
1399 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
1400 *cpp = valstr;
1401 return oldenv;
1402 }
1403 }
1404
1405 if (env == NULL) {
1406 env = VG_(arena_malloc)(VG_AR_CORE, sizeof(Char **) * 2);
1407 env[0] = valstr;
1408 env[1] = NULL;
1409
1410 *envp = env;
1411
1412 } else {
1413 Int envlen = (cpp-env) + 2;
1414 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1415
1416 for(cpp = newenv; *env; )
1417 *cpp++ = *env++;
1418 *cpp++ = valstr;
1419 *cpp++ = NULL;
1420
1421 oldenv = *envp;
1422
1423 *envp = newenv;
1424 }
1425
1426 return oldenv;
1427}
1428
1429Char* VG_(env_getenv) ( Char **env, Char* varname )
sewardjde4a1d02002-03-22 01:27:54 +00001430{
1431 Int i, n;
1432 n = VG_(strlen)(varname);
fitzhardinge98abfc72003-12-16 02:05:15 +00001433 for (i = 0; env[i] != NULL; i++) {
1434 Char* s = env[i];
sewardjde4a1d02002-03-22 01:27:54 +00001435 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1436 return & s[n+1];
1437 }
1438 }
1439 return NULL;
1440}
1441
fitzhardinge98abfc72003-12-16 02:05:15 +00001442/* We do getenv without libc's help by snooping around in
1443 VG_(client_envp) as determined at startup time. */
1444Char *VG_(getenv)(Char *varname)
1445{
1446 return VG_(env_getenv)(VG_(client_envp), varname);
1447}
sewardj4cf05692002-10-27 20:28:29 +00001448
rjwalshf5f536f2003-11-17 17:45:00 +00001449/* Support for getrlimit. */
1450Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
1451{
1452 Int res;
1453 /* res = getrlimit( resource, rlim ); */
1454 res = VG_(do_syscall)(__NR_getrlimit, (UInt)resource, (UInt)rlim);
1455 if(VG_(is_kerror)(res)) res = -1;
1456 return res;
1457}
1458
1459
fitzhardingef0046f22003-12-18 02:39:22 +00001460/* Support for setrlimit. */
1461Int VG_(setrlimit) (Int resource, struct vki_rlimit *rlim)
1462{
1463 Int res;
1464 /* res = setrlimit( resource, rlim ); */
1465 res = VG_(do_syscall)(__NR_setrlimit, (UInt)resource, (UInt)rlim);
1466 if(VG_(is_kerror)(res)) res = -1;
1467 return res;
1468}
1469
1470
rjwalshf5f536f2003-11-17 17:45:00 +00001471/* Support for getdents. */
1472Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
1473{
1474 Int res;
1475 /* res = getdents( fd, dirp, count ); */
1476 res = VG_(do_syscall)(__NR_getdents, fd, (UInt)dirp, count);
1477 if (VG_(is_kerror)(res)) res = -1;
1478 return res;
1479}
1480
1481/* Support for a readlink. */
1482Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
1483{
1484 Int res;
1485 /* res = readlink( path, buf, bufsiz ); */
1486 res = VG_(do_syscall)(__NR_readlink, (UInt)path, (UInt)buf, bufsiz);
1487 if (VG_(is_kerror)(res)) res = -1;
1488 return res;
1489}
1490
sewardjde4a1d02002-03-22 01:27:54 +00001491/* You'd be amazed how many places need to know the current pid. */
1492Int VG_(getpid) ( void )
1493{
1494 Int res;
1495 /* res = getpid(); */
jsgf855d93d2003-10-13 22:26:55 +00001496 res = VG_(do_syscall)(__NR_getpid);
1497 return res;
1498}
1499
1500Int VG_(getpgrp) ( void )
1501{
1502 Int res;
1503 /* res = getpgid(); */
1504 res = VG_(do_syscall)(__NR_getpgrp);
sewardjde4a1d02002-03-22 01:27:54 +00001505 return res;
1506}
1507
sewardj4cf05692002-10-27 20:28:29 +00001508Int VG_(getppid) ( void )
1509{
1510 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001511 res = VG_(do_syscall)(__NR_getppid);
sewardj4cf05692002-10-27 20:28:29 +00001512 return res;
1513}
1514
jsgf855d93d2003-10-13 22:26:55 +00001515Int VG_(setpgid) ( Int pid, Int pgrp )
1516{
1517 return VG_(do_syscall)(__NR_setpgid, pid, pgrp);
1518}
sewardj4cf05692002-10-27 20:28:29 +00001519
sewardje6a25242002-04-21 22:03:07 +00001520/* Return -1 if error, else 0. NOTE does not indicate return code of
1521 child! */
1522Int VG_(system) ( Char* cmd )
1523{
1524 Int pid, res;
sewardje6a25242002-04-21 22:03:07 +00001525 if (cmd == NULL)
1526 return 1;
jsgf855d93d2003-10-13 22:26:55 +00001527 pid = VG_(do_syscall)(__NR_fork);
sewardje6a25242002-04-21 22:03:07 +00001528 if (VG_(is_kerror)(pid))
1529 return -1;
1530 if (pid == 0) {
1531 /* child */
nethercoteff9721d2004-01-26 17:10:01 +00001532 static Char** envp = NULL;
sewardje6a25242002-04-21 22:03:07 +00001533 Char* argv[4];
nethercoteff9721d2004-01-26 17:10:01 +00001534
1535 if (envp == NULL) {
1536 Int i;
1537 Char* ld_preload_str = NULL;
1538 Char* ld_library_path_str = NULL;
1539 Char* buf;
1540
1541 envp = VG_(env_clone)(VG_(client_envp));
1542
1543 for (i = 0; envp[i] != NULL; i++) {
1544 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
1545 ld_preload_str = &envp[i][11];
1546 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
1547 ld_library_path_str = &envp[i][16];
1548 }
1549
1550 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
1551
1552 VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
1553 VG_(mash_colon_env)(ld_preload_str, buf);
1554
1555 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
1556 VG_(mash_colon_env)(ld_preload_str, buf);
1557
1558 VG_(sprintf)(buf, "%s*", VG_(libdir));
1559 VG_(mash_colon_env)(ld_library_path_str, buf);
1560
1561 VG_(env_unsetenv)(envp, VALGRINDCLO);
1562
1563 VG_(arena_free)(VG_AR_CORE, buf);
1564 }
1565
sewardje6a25242002-04-21 22:03:07 +00001566 argv[0] = "/bin/sh";
1567 argv[1] = "-c";
1568 argv[2] = cmd;
1569 argv[3] = 0;
nethercoteff9721d2004-01-26 17:10:01 +00001570
jsgf855d93d2003-10-13 22:26:55 +00001571 (void)VG_(do_syscall)(__NR_execve,
nethercoteff9721d2004-01-26 17:10:01 +00001572 (UInt)"/bin/sh", (UInt)argv, (UInt)envp);
1573
sewardje6a25242002-04-21 22:03:07 +00001574 /* If we're still alive here, execve failed. */
1575 return -1;
1576 } else {
1577 /* parent */
jsgf855d93d2003-10-13 22:26:55 +00001578 res = VG_(do_syscall)(__NR_waitpid, pid, (UInt)NULL, 0);
sewardje6a25242002-04-21 22:03:07 +00001579 if (VG_(is_kerror)(res)) {
1580 return -1;
1581 } else {
1582 return 0;
1583 }
1584 }
1585}
1586
1587
sewardjde4a1d02002-03-22 01:27:54 +00001588/* ---------------------------------------------------------------------
fitzhardinge66871692004-01-25 03:32:58 +00001589 Support for a millisecond-granularity timer.
sewardj5f07b662002-04-23 16:52:51 +00001590 ------------------------------------------------------------------ */
1591
sewardj5f07b662002-04-23 16:52:51 +00001592UInt VG_(read_millisecond_timer) ( void )
1593{
fitzhardinge426f9e62004-01-25 03:44:18 +00001594 static ULong base = 0;
fitzhardinge66871692004-01-25 03:32:58 +00001595 struct vki_timeval tv_now;
1596 ULong now;
sewardj5f07b662002-04-23 16:52:51 +00001597 Int res;
sewardj5f07b662002-04-23 16:52:51 +00001598
fitzhardinge66871692004-01-25 03:32:58 +00001599 res = VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now,
1600 (UInt)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001601
fitzhardinge66871692004-01-25 03:32:58 +00001602 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1603
1604 if (base == 0)
1605 base = now;
sewardj5f07b662002-04-23 16:52:51 +00001606
fitzhardinge66871692004-01-25 03:32:58 +00001607 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +00001608}
1609
1610
sewardj5f07b662002-04-23 16:52:51 +00001611/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001612 Primitive support for bagging memory via mmap.
1613 ------------------------------------------------------------------ */
1614
sewardje9047952002-06-05 20:28:33 +00001615void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001616{
1617 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001618 void* p;
fitzhardinge98abfc72003-12-16 02:05:15 +00001619
1620#if 0
1621 p = VG_(mmap)( (void *)VG_(valgrind_base), nBytes,
1622 VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC,
1623 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS, -1, 0 );
1624#else
1625 /* use brk, because it will definitely be in the valgrind address space */
1626 {
1627 Char *b = VG_(brk)(0);
1628
1629 p = (void *)PGROUNDUP(b);
1630
1631 b = VG_(brk)(p + PGROUNDUP(nBytes));
1632
1633 if (b != (p + PGROUNDUP(nBytes)))
1634 p = (void *)-1;
1635 }
1636#endif
1637
sewardjde4a1d02002-03-22 01:27:54 +00001638 if (p != ((void*)(-1))) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001639 vg_assert(p >= (void *)VG_(valgrind_mmap_end) && p < (void *)VG_(valgrind_end));
sewardjde4a1d02002-03-22 01:27:54 +00001640 tot_alloc += (UInt)nBytes;
1641 if (0)
sewardje9047952002-06-05 20:28:33 +00001642 VG_(printf)(
1643 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1644 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001645 return p;
1646 }
sewardj7c2020b2002-09-30 22:56:03 +00001647
njn25e49d8e72002-09-23 09:36:25 +00001648 VG_(printf)("\n");
daywalkerb1db1232003-09-26 00:26:07 +00001649 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %d bytes failed.\n",
1650 who, nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001651 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1652 tot_alloc);
1653 VG_(printf)("\n");
1654 VG_(printf)("This may mean that you have run out of swap space,\n");
1655 VG_(printf)("since running programs on valgrind increases their memory\n");
1656 VG_(printf)("usage at least 3 times. You might want to use 'top'\n");
1657 VG_(printf)("to determine whether you really have run out of swap.\n");
1658 VG_(printf)("If so, you may be able to work around it by adding a\n");
1659 VG_(printf)("temporary swap file -- this is easier than finding a\n");
1660 VG_(printf)("new swap partition. Go ask your sysadmin(s) [politely!]\n");
1661 VG_(printf)("\n");
1662 VG_(printf)("VG_(get_memory_from_mmap): out of memory! Fatal! Bye!\n");
1663 VG_(printf)("\n");
1664 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001665}
1666
njn25e49d8e72002-09-23 09:36:25 +00001667/* ---------------------------------------------------------------------
1668 Generally useful...
1669 ------------------------------------------------------------------ */
1670
1671Int VG_(log2) ( Int x )
1672{
1673 Int i;
1674 /* Any more than 32 and we overflow anyway... */
1675 for (i = 0; i < 32; i++) {
1676 if (1 << i == x) return i;
1677 }
1678 return -1;
1679}
1680
1681
njnd3b0c5f2003-09-30 14:43:54 +00001682// Generic shell sort. Like stdlib.h's qsort().
1683void VG_(ssort)( void* base, UInt nmemb, UInt size,
1684 Int (*compar)(void*, void*) )
1685{
1686 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1687 9841, 29524, 88573, 265720,
1688 797161, 2391484 };
1689 Int lo = 0;
1690 Int hi = nmemb-1;
1691 Int i, j, h, bigN, hp;
1692
1693 bigN = hi - lo + 1; if (bigN < 2) return;
1694 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1695 vg_assert(0 <= hp && hp < 14);
1696
1697 #define SORT \
1698 for ( ; hp >= 0; hp--) { \
1699 h = incs[hp]; \
njn92c54362003-10-15 14:00:35 +00001700 for (i = lo + h; i <= hi; i++) { \
njnd3b0c5f2003-09-30 14:43:54 +00001701 ASSIGN(v,0, a,i); \
1702 j = i; \
njn92c54362003-10-15 14:00:35 +00001703 while (COMPAR(a,(j-h), v,0) > 0) { \
njnd3b0c5f2003-09-30 14:43:54 +00001704 ASSIGN(a,j, a,(j-h)); \
1705 j = j - h; \
1706 if (j <= (lo + h - 1)) break; \
1707 } \
1708 ASSIGN(a,j, v,0); \
njnd3b0c5f2003-09-30 14:43:54 +00001709 } \
1710 }
1711
1712 // Specialised cases
1713 if (sizeof(UInt) == size) {
1714
1715 #define ASSIGN(dst, dsti, src, srci) \
1716 (dst)[(dsti)] = (src)[(srci)];
1717
1718 #define COMPAR(dst, dsti, src, srci) \
1719 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1720
1721 UInt* a = (UInt*)base;
1722 UInt v[1];
1723
1724 SORT;
1725
1726 } else if (sizeof(UShort) == size) {
1727 UShort* a = (UShort*)base;
1728 UShort v[1];
1729
1730 SORT;
1731
1732 } else if (sizeof(UChar) == size) {
1733 UChar* a = (UChar*)base;
1734 UChar v[1];
1735
1736 SORT;
1737
1738 #undef ASSIGN
1739 #undef COMPAR
1740
1741 // General case
1742 } else {
njn92c54362003-10-15 14:00:35 +00001743 char* a = base;
1744 char v[size]; // will be at least 'size' bytes
njnd3b0c5f2003-09-30 14:43:54 +00001745
1746 #define ASSIGN(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001747 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
njnd3b0c5f2003-09-30 14:43:54 +00001748
1749 #define COMPAR(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001750 compar( &dst[size*(dsti)], &src[size*(srci)] )
njnd3b0c5f2003-09-30 14:43:54 +00001751
1752 SORT;
1753
1754 #undef ASSIGN
1755 #undef COMPAR
1756 }
1757 #undef SORT
1758}
1759
sewardj73cf3bc2002-11-03 03:20:15 +00001760/* ---------------------------------------------------------------------
1761 Gruesome hackery for connecting to a logging server over the network.
1762 This is all very Linux-kernel specific.
1763 ------------------------------------------------------------------ */
1764
1765/* Various needed constants from the kernel iface (2.4),
1766 /usr/src/linux-2.4.9-31 */
1767
1768/* kernel, ./include/linux/net.h */
rjwalshf5f536f2003-11-17 17:45:00 +00001769#define SYS_SOCKET 1 /* sys_socket(2) */
1770#define SYS_CONNECT 3 /* sys_connect(2) */
1771#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
1772#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
1773#define SYS_SEND 9 /* sys_send(2) */
1774#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
sewardj73cf3bc2002-11-03 03:20:15 +00001775
1776typedef UInt __u32;
1777
1778/* Internet address. */
1779struct vki_in_addr {
1780 __u32 s_addr;
1781};
1782
1783/* kernel, include/linux/socket.h */
sewardj73cf3bc2002-11-03 03:20:15 +00001784#define AF_INET 2 /* Internet IP Protocol */
sewardj570f8902002-11-03 11:44:36 +00001785#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
sewardj73cf3bc2002-11-03 03:20:15 +00001786
1787/* kernel, ./include/asm-i386/socket.h */
1788#define SOCK_STREAM 1 /* stream (connection) socket */
1789
1790/* kernel, /usr/src/linux-2.4.9-31/linux/include/in.h */
1791/* Structure describing an Internet (IP) socket address. */
1792#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
1793struct vki_sockaddr_in {
1794 vki_sa_family_t sin_family; /* Address family */
1795 unsigned short int sin_port; /* Port number */
1796 struct vki_in_addr sin_addr; /* Internet address */
1797
1798 /* Pad to size of `struct sockaddr'. */
1799 unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
1800 sizeof(unsigned short int) -
1801 sizeof(struct vki_in_addr)];
1802};
1803
1804
1805static
1806Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1807
1808static
1809Int my_socket ( Int domain, Int type, Int protocol );
1810
1811static
1812Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1813 Int addrlen );
1814
1815static
1816UInt my_htonl ( UInt x )
1817{
1818 return
1819 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1820 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1821}
1822
1823static
1824UShort my_htons ( UShort x )
1825{
1826 return
1827 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1828}
1829
1830
1831/* The main function.
1832
1833 Supplied string contains either an ip address "192.168.0.1" or
1834 an ip address and port pair, "192.168.0.1:1500". Parse these,
1835 and return:
1836 -1 if there is a parse error
1837 -2 if no parse error, but specified host:port cannot be opened
1838 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001839 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001840*/
1841Int VG_(connect_via_socket)( UChar* str )
1842{
1843 Int sd, res;
1844 struct vki_sockaddr_in servAddr;
1845 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001846 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001847 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1848 if (!ok)
1849 return -1;
1850
1851 if (0)
1852 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1853 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1854 (ip >> 8) & 0xFF, ip & 0xFF,
1855 (UInt)port );
1856
1857 servAddr.sin_family = AF_INET;
1858 servAddr.sin_addr.s_addr = my_htonl(ip);
1859 servAddr.sin_port = my_htons(port);
1860
1861 /* create socket */
1862 sd = my_socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1863 if (sd < 0) {
1864 /* this shouldn't happen ... nevertheless */
1865 return -2;
1866 }
1867
1868 /* connect to server */
1869 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1870 sizeof(servAddr));
1871 if (res < 0) {
1872 /* connection failed */
1873 return -2;
1874 }
1875
1876 return sd;
1877}
1878
1879
1880/* Let d = one or more digits. Accept either:
1881 d.d.d.d or d.d.d.d:d
1882*/
1883Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1884{
1885# define GET_CH ((*str) ? (*str++) : 0)
1886 UInt ipa, i, j, c, any;
1887 ipa = 0;
1888 for (i = 0; i < 4; i++) {
1889 j = 0;
1890 any = 0;
1891 while (1) {
1892 c = GET_CH;
1893 if (c < '0' || c > '9') break;
1894 j = 10 * j + (int)(c - '0');
1895 any = 1;
1896 }
1897 if (any == 0 || j > 255) goto syntaxerr;
1898 ipa = (ipa << 8) + j;
1899 if (i <= 2 && c != '.') goto syntaxerr;
1900 }
1901 if (c == 0 || c == ':')
1902 *ip_addr = ipa;
1903 if (c == 0) goto ok;
1904 if (c != ':') goto syntaxerr;
1905 j = 0;
1906 any = 0;
1907 while (1) {
1908 c = GET_CH;
1909 if (c < '0' || c > '9') break;
1910 j = j * 10 + (int)(c - '0');
1911 any = 1;
1912 if (j > 65535) goto syntaxerr;
1913 }
1914 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001915 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001916 *port = (UShort)j;
1917 ok:
1918 return 1;
1919 syntaxerr:
1920 return 0;
1921# undef GET_CH
1922}
1923
1924
1925static
1926Int my_socket ( Int domain, Int type, Int protocol )
1927{
1928 Int res;
1929 UInt args[3];
1930 args[0] = domain;
1931 args[1] = type;
1932 args[2] = protocol;
jsgf855d93d2003-10-13 22:26:55 +00001933 res = VG_(do_syscall)(__NR_socketcall, SYS_SOCKET, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001934 if (VG_(is_kerror)(res))
1935 res = -1;
1936 return res;
1937}
1938
1939static
1940Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1941 Int addrlen )
1942{
1943 Int res;
1944 UInt args[3];
1945 args[0] = sockfd;
1946 args[1] = (UInt)serv_addr;
1947 args[2] = addrlen;
jsgf855d93d2003-10-13 22:26:55 +00001948 res = VG_(do_syscall)(__NR_socketcall, SYS_CONNECT, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001949 if (VG_(is_kerror)(res))
1950 res = -1;
1951 return res;
1952}
1953
1954Int VG_(write_socket)( Int sd, void *msg, Int count )
1955{
1956 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001957
1958 /* Requests not to send SIGPIPE on errors on stream oriented
1959 sockets when the other end breaks the connection. The EPIPE
1960 error is still returned. */
1961 Int flags = MSG_NOSIGNAL;
1962
sewardj73cf3bc2002-11-03 03:20:15 +00001963 Int res;
1964 UInt args[4];
1965 args[0] = sd;
1966 args[1] = (UInt)msg;
1967 args[2] = count;
1968 args[3] = flags;
jsgf855d93d2003-10-13 22:26:55 +00001969 res = VG_(do_syscall)(__NR_socketcall, SYS_SEND, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001970 if (VG_(is_kerror)(res))
1971 res = -1;
1972 return res;
1973}
1974
rjwalshf5f536f2003-11-17 17:45:00 +00001975Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1976{
1977 Int res;
1978 UInt args[3];
1979 args[0] = sd;
1980 args[1] = (UInt)name;
1981 args[2] = (UInt)namelen;
1982 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKNAME, (UInt)&args);
1983 if(VG_(is_kerror)(res))
1984 res = -1;
1985 return res;
1986}
1987
1988Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1989{
1990 Int res;
1991 UInt args[3];
1992 args[0] = sd;
1993 args[1] = (UInt)name;
1994 args[2] = (UInt)namelen;
1995 res = VG_(do_syscall)(__NR_socketcall, SYS_GETPEERNAME, (UInt)&args);
1996 if(VG_(is_kerror)(res))
1997 res = -1;
1998 return res;
1999}
2000
2001Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
2002 Int *optlen)
2003{
2004 Int res;
2005 UInt args[5];
2006 args[0] = sd;
2007 args[1] = (UInt)level;
2008 args[2] = (UInt)optname;
2009 args[3] = (UInt)optval;
2010 args[4] = (UInt)optlen;
2011 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKOPT, (UInt)&args);
2012 if(VG_(is_kerror)(res))
2013 res = -1;
2014 return res;
2015}
2016
sewardjde4a1d02002-03-22 01:27:54 +00002017
2018/*--------------------------------------------------------------------*/
2019/*--- end vg_mylibc.c ---*/
2020/*--------------------------------------------------------------------*/