blob: dbf78ebdeb1c52ba920bd1908f94fbd7ce68dcd2 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Reimplementation of some C library stuff, to avoid depending ---*/
4/*--- on libc.so. ---*/
5/*--- vg_mylibc.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
njnc9539842002-10-02 13:26:35 +00009 This file is part of Valgrind, an extensible x86 protected-mode
10 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000011
njn0e1b5142003-04-15 14:58:06 +000012 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
32
33#include "vg_include.h"
34
sewardjde4a1d02002-03-22 01:27:54 +000035/* ---------------------------------------------------------------------
36 Wrappers around system calls, and other stuff, to do with signals.
37 ------------------------------------------------------------------ */
38
39/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
40 success and -1 on error.
41*/
42Int VG_(ksigfillset)( vki_ksigset_t* set )
43{
44 Int i;
45 if (set == NULL)
46 return -1;
47 for (i = 0; i < VKI_KNSIG_WORDS; i++)
48 set->ws[i] = 0xFFFFFFFF;
49 return 0;
50}
51
52Int VG_(ksigemptyset)( vki_ksigset_t* set )
53{
54 Int i;
55 if (set == NULL)
56 return -1;
57 for (i = 0; i < VKI_KNSIG_WORDS; i++)
58 set->ws[i] = 0x0;
59 return 0;
60}
61
sewardjb48e5002002-05-13 00:16:03 +000062Bool VG_(kisemptysigset)( vki_ksigset_t* set )
63{
64 Int i;
65 vg_assert(set != NULL);
66 for (i = 0; i < VKI_KNSIG_WORDS; i++)
67 if (set->ws[i] != 0x0) return False;
68 return True;
69}
70
sewardj018f7622002-05-15 21:13:39 +000071Bool VG_(kisfullsigset)( vki_ksigset_t* set )
72{
73 Int i;
74 vg_assert(set != NULL);
75 for (i = 0; i < VKI_KNSIG_WORDS; i++)
sewardj05bcdcb2003-05-18 10:05:38 +000076 if (set->ws[i] != (UInt)(~0x0)) return False;
sewardj018f7622002-05-15 21:13:39 +000077 return True;
78}
79
80
sewardjde4a1d02002-03-22 01:27:54 +000081Int VG_(ksigaddset)( vki_ksigset_t* set, Int signum )
82{
83 if (set == NULL)
84 return -1;
njn25e49d8e72002-09-23 09:36:25 +000085 if (signum < 1 || signum > VKI_KNSIG)
sewardjde4a1d02002-03-22 01:27:54 +000086 return -1;
87 signum--;
88 set->ws[signum / VKI_KNSIG_BPW] |= (1 << (signum % VKI_KNSIG_BPW));
89 return 0;
90}
91
sewardj018f7622002-05-15 21:13:39 +000092Int VG_(ksigdelset)( vki_ksigset_t* set, Int signum )
93{
94 if (set == NULL)
95 return -1;
njn25e49d8e72002-09-23 09:36:25 +000096 if (signum < 1 || signum > VKI_KNSIG)
sewardj018f7622002-05-15 21:13:39 +000097 return -1;
98 signum--;
99 set->ws[signum / VKI_KNSIG_BPW] &= ~(1 << (signum % VKI_KNSIG_BPW));
100 return 0;
101}
102
sewardjde4a1d02002-03-22 01:27:54 +0000103Int VG_(ksigismember) ( vki_ksigset_t* set, Int signum )
104{
105 if (set == NULL)
sewardjb48e5002002-05-13 00:16:03 +0000106 return 0;
njn25e49d8e72002-09-23 09:36:25 +0000107 if (signum < 1 || signum > VKI_KNSIG)
sewardjb48e5002002-05-13 00:16:03 +0000108 return 0;
sewardjde4a1d02002-03-22 01:27:54 +0000109 signum--;
110 if (1 & ((set->ws[signum / VKI_KNSIG_BPW]) >> (signum % VKI_KNSIG_BPW)))
111 return 1;
112 else
113 return 0;
114}
115
116
sewardjb48e5002002-05-13 00:16:03 +0000117/* Add all signals in src to dst. */
118void VG_(ksigaddset_from_set)( vki_ksigset_t* dst, vki_ksigset_t* src )
119{
120 Int i;
121 vg_assert(dst != NULL && src != NULL);
122 for (i = 0; i < VKI_KNSIG_WORDS; i++)
123 dst->ws[i] |= src->ws[i];
124}
125
126/* Remove all signals in src from dst. */
127void VG_(ksigdelset_from_set)( vki_ksigset_t* dst, vki_ksigset_t* src )
128{
129 Int i;
130 vg_assert(dst != NULL && src != NULL);
131 for (i = 0; i < VKI_KNSIG_WORDS; i++)
132 dst->ws[i] &= ~(src->ws[i]);
133}
134
135
sewardjde4a1d02002-03-22 01:27:54 +0000136/* The functions sigaction, sigprocmask, sigpending and sigsuspend
137 return 0 on success and -1 on error.
138*/
139Int VG_(ksigprocmask)( Int how,
140 const vki_ksigset_t* set,
141 vki_ksigset_t* oldset)
142{
143 Int res
jsgf855d93d2003-10-13 22:26:55 +0000144 = VG_(do_syscall)(__NR_rt_sigprocmask,
145 how, (UInt)set, (UInt)oldset,
146 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
sewardjde4a1d02002-03-22 01:27:54 +0000147 return VG_(is_kerror)(res) ? -1 : 0;
148}
149
150
151Int VG_(ksigaction) ( Int signum,
152 const vki_ksigaction* act,
153 vki_ksigaction* oldact)
154{
155 Int res
jsgf855d93d2003-10-13 22:26:55 +0000156 = VG_(do_syscall)(__NR_rt_sigaction,
157 signum, (UInt)act, (UInt)oldact,
158 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
sewardj018f7622002-05-15 21:13:39 +0000159 /* VG_(printf)("res = %d\n",res); */
sewardjde4a1d02002-03-22 01:27:54 +0000160 return VG_(is_kerror)(res) ? -1 : 0;
161}
162
163
164Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss )
165{
166 Int res
jsgf855d93d2003-10-13 22:26:55 +0000167 = VG_(do_syscall)(__NR_sigaltstack, (UInt)ss, (UInt)oss);
sewardjde4a1d02002-03-22 01:27:54 +0000168 return VG_(is_kerror)(res) ? -1 : 0;
169}
170
jsgf855d93d2003-10-13 22:26:55 +0000171Int VG_(ksigtimedwait)( const vki_ksigset_t *set, vki_ksiginfo_t *info,
172 const struct vki_timespec *timeout )
173{
174 Int res = VG_(do_syscall)(__NR_rt_sigtimedwait, set, info, timeout, sizeof(*set));
175
176 return VG_(is_kerror)(res) ? -1 : res;
177}
sewardjde4a1d02002-03-22 01:27:54 +0000178
179Int VG_(ksignal)(Int signum, void (*sighandler)(Int))
180{
181 Int res;
182 vki_ksigaction sa;
183 sa.ksa_handler = sighandler;
184 sa.ksa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
185 sa.ksa_restorer = NULL;
186 res = VG_(ksigemptyset)( &sa.ksa_mask );
187 vg_assert(res == 0);
jsgf855d93d2003-10-13 22:26:55 +0000188 res = VG_(do_syscall)(__NR_rt_sigaction,
189 signum, (UInt)(&sa), (UInt)NULL,
190 VKI_KNSIG_WORDS * VKI_BYTES_PER_WORD);
sewardjde4a1d02002-03-22 01:27:54 +0000191 return VG_(is_kerror)(res) ? -1 : 0;
192}
193
194
sewardjdcaf3122002-09-30 23:12:33 +0000195Int VG_(kkill)( Int pid, Int signo )
sewardj018f7622002-05-15 21:13:39 +0000196{
jsgf855d93d2003-10-13 22:26:55 +0000197 Int res = VG_(do_syscall)(__NR_kill, pid, signo);
sewardj018f7622002-05-15 21:13:39 +0000198 return VG_(is_kerror)(res) ? -1 : 0;
199}
200
201
jsgf855d93d2003-10-13 22:26:55 +0000202Int VG_(ktkill)( Int tid, Int signo )
203{
204 Int ret = -VKI_ENOSYS;
205
206#ifdef __NR_tkill
207 ret = VG_(do_syscall)(__NR_tkill, tid, signo);
208#endif /* __NR_tkill */
209
210 if (ret == -VKI_ENOSYS)
211 ret = VG_(do_syscall)(__NR_kill, tid, signo);
212
213 return VG_(is_kerror)(ret) ? -1 : 0;
214}
215
sewardjdcaf3122002-09-30 23:12:33 +0000216Int VG_(ksigpending) ( vki_ksigset_t* set )
sewardjefbfcdf2002-06-19 17:35:45 +0000217{
jsgf855d93d2003-10-13 22:26:55 +0000218 Int res = VG_(do_syscall)(__NR_sigpending, (UInt)set);
sewardjefbfcdf2002-06-19 17:35:45 +0000219 return VG_(is_kerror)(res) ? -1 : 0;
220}
221
jsgf855d93d2003-10-13 22:26:55 +0000222Int VG_(waitpid)(Int pid, Int *status, Int options)
223{
224 Int ret = VG_(do_syscall)(__NR_wait4, pid, status, options, NULL);
225
226 return VG_(is_kerror)(ret) ? -1 : ret;
227}
228
229Int VG_(gettid)(void)
230{
231 Int ret;
232
233 ret = VG_(do_syscall)(__NR_gettid);
234
235 if (ret == -VKI_ENOSYS)
236 ret = VG_(do_syscall)(__NR_getpid);
237
238 return ret;
239}
240
241
sewardjefbfcdf2002-06-19 17:35:45 +0000242
sewardjde4a1d02002-03-22 01:27:54 +0000243/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000244 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000245 ------------------------------------------------------------------ */
246
247/* Returns -1 on failure. */
248void* VG_(mmap)( void* start, UInt length,
249 UInt prot, UInt flags, UInt fd, UInt offset)
250{
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 );
fitzhardinge98abfc72003-12-16 02:05:15 +0000309 if (!VG_(is_kerror))
310 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
njn25e49d8e72002-09-23 09:36:25 +00001037/* Wrapper to avoid exposing skins to ArenaId's */
1038Char* VG_(strdup) ( const Char* s )
1039{
1040 return VG_(arena_strdup) ( VG_AR_SKIN, s );
1041}
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
1206 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_MAX_FD+1);
1207 if (newfd != -1)
1208 VG_(close)(oldfd);
1209
1210 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
1211
1212 vg_assert(newfd > VG_MAX_FD);
1213 return newfd;
1214}
1215
1216
1217
sewardjde4a1d02002-03-22 01:27:54 +00001218/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001219Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1220{
sewardjde4a1d02002-03-22 01:27:54 +00001221 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001222
njn25e49d8e72002-09-23 09:36:25 +00001223 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001224 /* This gets a segmentation fault if pathname isn't a valid file.
1225 I don't know why. It seems like the call to open is getting
1226 intercepted and messed with by glibc ... */
1227 /* fd = open( pathname, O_RDONLY ); */
1228 /* ... so we go direct to the horse's mouth, which seems to work
1229 ok: */
jsgf855d93d2003-10-13 22:26:55 +00001230 fd = VG_(do_syscall)(__NR_open, (UInt)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001231 /* VG_(printf)("result = %d\n", fd); */
jsgff3c3f1a2003-10-14 22:13:28 +00001232 /* return -ve error code */
njn4f9c9342002-04-29 16:03:24 +00001233 return fd;
1234}
sewardjde4a1d02002-03-22 01:27:54 +00001235
jsgf855d93d2003-10-13 22:26:55 +00001236Int VG_(pipe) ( Int fd[2] )
1237{
1238 Int ret = VG_(do_syscall)(__NR_pipe, fd);
1239 return VG_(is_kerror)(ret) ? -1 : 0;
1240}
1241
sewardjde4a1d02002-03-22 01:27:54 +00001242void VG_(close) ( Int fd )
1243{
jsgf855d93d2003-10-13 22:26:55 +00001244 VG_(do_syscall)(__NR_close, fd);
sewardjde4a1d02002-03-22 01:27:54 +00001245}
1246
1247
1248Int VG_(read) ( Int fd, void* buf, Int count)
1249{
1250 Int res;
1251 /* res = read( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001252 res = VG_(do_syscall)(__NR_read, fd, (UInt)buf, count);
1253 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001254 return res;
1255}
1256
jsgf855d93d2003-10-13 22:26:55 +00001257Int VG_(write) ( Int fd, const void* buf, Int count)
sewardjde4a1d02002-03-22 01:27:54 +00001258{
1259 Int res;
1260 /* res = write( fd, buf, count ); */
jsgf855d93d2003-10-13 22:26:55 +00001261 res = VG_(do_syscall)(__NR_write, fd, (UInt)buf, count);
1262 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001263 return res;
1264}
1265
rjwalshf5f536f2003-11-17 17:45:00 +00001266Int VG_(lseek) ( Int fd, Long offset, Int whence)
1267{
1268 Int res;
1269 /* res = lseek( fd, offset, whence ); */
1270 res = VG_(do_syscall)(__NR_lseek, fd, (UInt)offset, whence);
1271 if (VG_(is_kerror)(res)) res = -1;
1272 return res;
1273}
1274
sewardjb3586202002-05-09 17:38:13 +00001275Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1276{
1277 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001278 res = VG_(do_syscall)(__NR_stat, (UInt)file_name, (UInt)buf);
fitzhardingee1c06d82003-10-30 07:21:44 +00001279 return res; /* return -ve error */
njn41557122002-10-14 09:25:37 +00001280}
1281
jsgf855d93d2003-10-13 22:26:55 +00001282Int VG_(fstat) ( Int fd, struct vki_stat* buf )
1283{
1284 Int res;
1285 res = VG_(do_syscall)(__NR_fstat, (UInt)fd, (UInt)buf);
1286 return VG_(is_kerror)(res) ? (-1) : 0;
1287}
1288
1289Int VG_(dup2) ( Int oldfd, Int newfd )
1290{
1291 Int res;
1292 res = VG_(do_syscall)(__NR_dup2, (UInt)oldfd, (UInt)newfd);
1293 return VG_(is_kerror)(res) ? (-1) : res;
1294}
1295
njn41557122002-10-14 09:25:37 +00001296Int VG_(rename) ( Char* old_name, Char* new_name )
1297{
1298 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001299 res = VG_(do_syscall)(__NR_rename, (UInt)old_name, (UInt)new_name);
njn41557122002-10-14 09:25:37 +00001300 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001301}
1302
njn4aca2d22002-10-04 10:29:38 +00001303Int VG_(unlink) ( Char* file_name )
1304{
1305 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001306 res = VG_(do_syscall)(__NR_unlink, (UInt)file_name);
njn41557122002-10-14 09:25:37 +00001307 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001308}
1309
njn13f02932003-04-30 20:23:58 +00001310/* Nb: we do not allow the Linux extension which malloc()s memory for the
1311 buffer if buf==NULL, because we don't want Linux calling malloc() */
1312Char* VG_(getcwd) ( Char* buf, Int size )
1313{
1314 Int res;
1315 vg_assert(buf != NULL);
jsgf855d93d2003-10-13 22:26:55 +00001316 res = VG_(do_syscall)(__NR_getcwd, (UInt)buf, (UInt)size);
njn13f02932003-04-30 20:23:58 +00001317 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1318}
1319
njn99ccf082003-09-30 13:51:23 +00001320/* Alternative version that does allocate the memory. Easier to use. */
1321Bool VG_(getcwd_alloc) ( Char** out )
1322{
1323 UInt size = 4;
1324
1325 *out = NULL;
1326 while (True) {
1327 *out = VG_(malloc)(size);
1328 if (NULL == VG_(getcwd)(*out, size)) {
1329 VG_(free)(*out);
1330 if (size > 65535)
1331 return False;
1332 size *= 2;
1333 } else {
1334 return True;
1335 }
1336 }
1337}
1338
njn13f02932003-04-30 20:23:58 +00001339
1340/* ---------------------------------------------------------------------
1341 Misc functions looking for a proper home.
1342 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001343
fitzhardinge98abfc72003-12-16 02:05:15 +00001344void VG_(env_unsetenv) ( Char **env, const Char *varname )
1345{
1346 Char **from;
1347 Char **to = NULL;
1348 Int len = VG_(strlen)(varname);
1349
1350 for(from = to = env; from && *from; from++) {
1351 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
1352 *to = *from;
1353 to++;
1354 }
1355 }
1356 *to = *from;
1357}
1358
1359/* set the environment; returns the old env if a new one was allocated */
1360Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
1361{
1362 Char **env = (*envp);
1363 Char **cpp;
1364 Int len = VG_(strlen)(varname);
1365 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, len + VG_(strlen)(val) + 2);
1366 Char **oldenv = NULL;
1367
1368 VG_(sprintf)(valstr, "%s=%s", varname, val);
1369
1370 for(cpp = env; cpp && *cpp; cpp++) {
1371 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
1372 *cpp = valstr;
1373 return oldenv;
1374 }
1375 }
1376
1377 if (env == NULL) {
1378 env = VG_(arena_malloc)(VG_AR_CORE, sizeof(Char **) * 2);
1379 env[0] = valstr;
1380 env[1] = NULL;
1381
1382 *envp = env;
1383
1384 } else {
1385 Int envlen = (cpp-env) + 2;
1386 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1387
1388 for(cpp = newenv; *env; )
1389 *cpp++ = *env++;
1390 *cpp++ = valstr;
1391 *cpp++ = NULL;
1392
1393 oldenv = *envp;
1394
1395 *envp = newenv;
1396 }
1397
1398 return oldenv;
1399}
1400
1401Char* VG_(env_getenv) ( Char **env, Char* varname )
sewardjde4a1d02002-03-22 01:27:54 +00001402{
1403 Int i, n;
1404 n = VG_(strlen)(varname);
fitzhardinge98abfc72003-12-16 02:05:15 +00001405 for (i = 0; env[i] != NULL; i++) {
1406 Char* s = env[i];
sewardjde4a1d02002-03-22 01:27:54 +00001407 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1408 return & s[n+1];
1409 }
1410 }
1411 return NULL;
1412}
1413
fitzhardinge98abfc72003-12-16 02:05:15 +00001414/* We do getenv without libc's help by snooping around in
1415 VG_(client_envp) as determined at startup time. */
1416Char *VG_(getenv)(Char *varname)
1417{
1418 return VG_(env_getenv)(VG_(client_envp), varname);
1419}
sewardj4cf05692002-10-27 20:28:29 +00001420
rjwalshf5f536f2003-11-17 17:45:00 +00001421/* Support for getrlimit. */
1422Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
1423{
1424 Int res;
1425 /* res = getrlimit( resource, rlim ); */
1426 res = VG_(do_syscall)(__NR_getrlimit, (UInt)resource, (UInt)rlim);
1427 if(VG_(is_kerror)(res)) res = -1;
1428 return res;
1429}
1430
1431
1432/* Support for getdents. */
1433Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
1434{
1435 Int res;
1436 /* res = getdents( fd, dirp, count ); */
1437 res = VG_(do_syscall)(__NR_getdents, fd, (UInt)dirp, count);
1438 if (VG_(is_kerror)(res)) res = -1;
1439 return res;
1440}
1441
1442/* Support for a readlink. */
1443Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
1444{
1445 Int res;
1446 /* res = readlink( path, buf, bufsiz ); */
1447 res = VG_(do_syscall)(__NR_readlink, (UInt)path, (UInt)buf, bufsiz);
1448 if (VG_(is_kerror)(res)) res = -1;
1449 return res;
1450}
1451
sewardjde4a1d02002-03-22 01:27:54 +00001452/* You'd be amazed how many places need to know the current pid. */
1453Int VG_(getpid) ( void )
1454{
1455 Int res;
1456 /* res = getpid(); */
jsgf855d93d2003-10-13 22:26:55 +00001457 res = VG_(do_syscall)(__NR_getpid);
1458 return res;
1459}
1460
1461Int VG_(getpgrp) ( void )
1462{
1463 Int res;
1464 /* res = getpgid(); */
1465 res = VG_(do_syscall)(__NR_getpgrp);
sewardjde4a1d02002-03-22 01:27:54 +00001466 return res;
1467}
1468
sewardj4cf05692002-10-27 20:28:29 +00001469Int VG_(getppid) ( void )
1470{
1471 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001472 res = VG_(do_syscall)(__NR_getppid);
sewardj4cf05692002-10-27 20:28:29 +00001473 return res;
1474}
1475
jsgf855d93d2003-10-13 22:26:55 +00001476Int VG_(setpgid) ( Int pid, Int pgrp )
1477{
1478 return VG_(do_syscall)(__NR_setpgid, pid, pgrp);
1479}
sewardj4cf05692002-10-27 20:28:29 +00001480
sewardje6a25242002-04-21 22:03:07 +00001481/* Return -1 if error, else 0. NOTE does not indicate return code of
1482 child! */
1483Int VG_(system) ( Char* cmd )
1484{
1485 Int pid, res;
1486 void* environ[1] = { NULL };
1487 if (cmd == NULL)
1488 return 1;
jsgf855d93d2003-10-13 22:26:55 +00001489 pid = VG_(do_syscall)(__NR_fork);
sewardje6a25242002-04-21 22:03:07 +00001490 if (VG_(is_kerror)(pid))
1491 return -1;
1492 if (pid == 0) {
1493 /* child */
1494 Char* argv[4];
1495 argv[0] = "/bin/sh";
1496 argv[1] = "-c";
1497 argv[2] = cmd;
1498 argv[3] = 0;
jsgf855d93d2003-10-13 22:26:55 +00001499 (void)VG_(do_syscall)(__NR_execve,
1500 (UInt)"/bin/sh", (UInt)argv, (UInt)&environ);
sewardje6a25242002-04-21 22:03:07 +00001501 /* If we're still alive here, execve failed. */
1502 return -1;
1503 } else {
1504 /* parent */
jsgf855d93d2003-10-13 22:26:55 +00001505 res = VG_(do_syscall)(__NR_waitpid, pid, (UInt)NULL, 0);
sewardje6a25242002-04-21 22:03:07 +00001506 if (VG_(is_kerror)(res)) {
1507 return -1;
1508 } else {
1509 return 0;
1510 }
1511 }
1512}
1513
1514
sewardjde4a1d02002-03-22 01:27:54 +00001515/* ---------------------------------------------------------------------
sewardj5f07b662002-04-23 16:52:51 +00001516 Support for a millisecond-granularity counter using RDTSC.
1517 ------------------------------------------------------------------ */
1518
1519static __inline__ ULong do_rdtsc_insn ( void )
1520{
1521 ULong x;
1522 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
1523 return x;
1524}
1525
1526/* 0 = pre-calibration, 1 = calibration, 2 = running */
1527static Int rdtsc_calibration_state = 0;
1528static ULong rdtsc_ticks_per_millisecond = 0; /* invalid value */
1529
1530static struct vki_timeval rdtsc_cal_start_timeval;
1531static struct vki_timeval rdtsc_cal_end_timeval;
1532
1533static ULong rdtsc_cal_start_raw;
1534static ULong rdtsc_cal_end_raw;
1535
1536UInt VG_(read_millisecond_timer) ( void )
1537{
1538 ULong rdtsc_now;
njne7442cf2003-09-30 14:03:21 +00001539 // If called before rdtsc setup completed (eg. from SK_(pre_clo_init)())
1540 // just return 0.
1541 if (rdtsc_calibration_state < 2) return 0;
sewardj5f07b662002-04-23 16:52:51 +00001542 rdtsc_now = do_rdtsc_insn();
1543 vg_assert(rdtsc_now > rdtsc_cal_end_raw);
1544 rdtsc_now -= rdtsc_cal_end_raw;
1545 rdtsc_now /= rdtsc_ticks_per_millisecond;
1546 return (UInt)rdtsc_now;
1547}
1548
1549
1550void VG_(start_rdtsc_calibration) ( void )
1551{
1552 Int res;
1553 vg_assert(rdtsc_calibration_state == 0);
1554 rdtsc_calibration_state = 1;
1555 rdtsc_cal_start_raw = do_rdtsc_insn();
jsgf855d93d2003-10-13 22:26:55 +00001556 res = VG_(do_syscall)(__NR_gettimeofday, (UInt)&rdtsc_cal_start_timeval,
1557 (UInt)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001558 vg_assert(!VG_(is_kerror)(res));
1559}
1560
1561void VG_(end_rdtsc_calibration) ( void )
1562{
1563 Int res, loops;
1564 ULong cpu_clock_MHZ;
1565 ULong cal_clock_ticks;
1566 ULong cal_wallclock_microseconds;
1567 ULong wallclock_start_microseconds;
1568 ULong wallclock_end_microseconds;
1569 struct vki_timespec req;
1570 struct vki_timespec rem;
1571
1572 vg_assert(rdtsc_calibration_state == 1);
1573 rdtsc_calibration_state = 2;
1574
1575 /* Try and delay for 20 milliseconds, so that we can at least have
1576 some minimum level of accuracy. */
1577 req.tv_sec = 0;
1578 req.tv_nsec = 20 * 1000 * 1000;
1579 loops = 0;
1580 while (True) {
1581 res = VG_(nanosleep)(&req, &rem);
1582 vg_assert(res == 0 /*ok*/ || res == 1 /*interrupted*/);
1583 if (res == 0)
1584 break;
1585 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
1586 break;
1587 req = rem;
1588 loops++;
1589 if (loops > 100)
njne427a662002-10-02 11:08:25 +00001590 VG_(core_panic)("calibration nanosleep loop failed?!");
sewardj5f07b662002-04-23 16:52:51 +00001591 }
1592
1593 /* Now read both timers, and do the Math. */
1594 rdtsc_cal_end_raw = do_rdtsc_insn();
jsgf855d93d2003-10-13 22:26:55 +00001595 res = VG_(do_syscall)(__NR_gettimeofday, (UInt)&rdtsc_cal_end_timeval,
1596 (UInt)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001597
1598 vg_assert(rdtsc_cal_end_raw > rdtsc_cal_start_raw);
1599 cal_clock_ticks = rdtsc_cal_end_raw - rdtsc_cal_start_raw;
1600
1601 wallclock_start_microseconds
1602 = (1000000ULL * (ULong)(rdtsc_cal_start_timeval.tv_sec))
1603 + (ULong)(rdtsc_cal_start_timeval.tv_usec);
1604 wallclock_end_microseconds
1605 = (1000000ULL * (ULong)(rdtsc_cal_end_timeval.tv_sec))
1606 + (ULong)(rdtsc_cal_end_timeval.tv_usec);
1607 vg_assert(wallclock_end_microseconds > wallclock_start_microseconds);
1608 cal_wallclock_microseconds
1609 = wallclock_end_microseconds - wallclock_start_microseconds;
1610
1611 /* Since we just nanoslept for 20 ms ... */
1612 vg_assert(cal_wallclock_microseconds >= 20000);
1613
1614 /* Now we know (roughly) that cal_clock_ticks on RDTSC take
1615 cal_wallclock_microseconds elapsed time. Calculate the RDTSC
1616 ticks-per-millisecond value. */
1617 if (0)
1618 VG_(printf)("%lld ticks in %lld microseconds\n",
1619 cal_clock_ticks, cal_wallclock_microseconds );
1620
1621 rdtsc_ticks_per_millisecond
1622 = cal_clock_ticks / (cal_wallclock_microseconds / 1000ULL);
1623 cpu_clock_MHZ
1624 = (1000ULL * rdtsc_ticks_per_millisecond) / 1000000ULL;
1625 if (VG_(clo_verbosity) >= 1)
1626 VG_(message)(Vg_UserMsg, "Estimated CPU clock rate is %d MHz",
1627 (UInt)cpu_clock_MHZ);
sewardj09c55fd2002-06-13 11:37:41 +00001628 if (cpu_clock_MHZ < 50 || cpu_clock_MHZ > 10000)
njne427a662002-10-02 11:08:25 +00001629 VG_(core_panic)("end_rdtsc_calibration: "
sewardj09c55fd2002-06-13 11:37:41 +00001630 "estimated CPU MHz outside range 50 .. 10000");
sewardj5f07b662002-04-23 16:52:51 +00001631 /* Paranoia about division by zero later. */
1632 vg_assert(rdtsc_ticks_per_millisecond != 0);
1633 if (0)
1634 VG_(printf)("ticks per millisecond %llu\n",
1635 rdtsc_ticks_per_millisecond);
1636}
1637
1638
1639
1640/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001641 Primitive support for bagging memory via mmap.
1642 ------------------------------------------------------------------ */
1643
sewardje9047952002-06-05 20:28:33 +00001644void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001645{
1646 static UInt tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001647 void* p;
fitzhardinge98abfc72003-12-16 02:05:15 +00001648
1649#if 0
1650 p = VG_(mmap)( (void *)VG_(valgrind_base), nBytes,
1651 VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC,
1652 VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS, -1, 0 );
1653#else
1654 /* use brk, because it will definitely be in the valgrind address space */
1655 {
1656 Char *b = VG_(brk)(0);
1657
1658 p = (void *)PGROUNDUP(b);
1659
1660 b = VG_(brk)(p + PGROUNDUP(nBytes));
1661
1662 if (b != (p + PGROUNDUP(nBytes)))
1663 p = (void *)-1;
1664 }
1665#endif
1666
sewardjde4a1d02002-03-22 01:27:54 +00001667 if (p != ((void*)(-1))) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001668 vg_assert(p >= (void *)VG_(valgrind_mmap_end) && p < (void *)VG_(valgrind_end));
sewardjde4a1d02002-03-22 01:27:54 +00001669 tot_alloc += (UInt)nBytes;
1670 if (0)
sewardje9047952002-06-05 20:28:33 +00001671 VG_(printf)(
1672 "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n",
1673 tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001674 return p;
1675 }
sewardj7c2020b2002-09-30 22:56:03 +00001676
njn25e49d8e72002-09-23 09:36:25 +00001677 VG_(printf)("\n");
daywalkerb1db1232003-09-26 00:26:07 +00001678 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %d bytes failed.\n",
1679 who, nBytes);
njn25e49d8e72002-09-23 09:36:25 +00001680 VG_(printf)("VG_(get_memory_from_mmap): %d bytes already allocated.\n",
1681 tot_alloc);
1682 VG_(printf)("\n");
1683 VG_(printf)("This may mean that you have run out of swap space,\n");
1684 VG_(printf)("since running programs on valgrind increases their memory\n");
1685 VG_(printf)("usage at least 3 times. You might want to use 'top'\n");
1686 VG_(printf)("to determine whether you really have run out of swap.\n");
1687 VG_(printf)("If so, you may be able to work around it by adding a\n");
1688 VG_(printf)("temporary swap file -- this is easier than finding a\n");
1689 VG_(printf)("new swap partition. Go ask your sysadmin(s) [politely!]\n");
1690 VG_(printf)("\n");
1691 VG_(printf)("VG_(get_memory_from_mmap): out of memory! Fatal! Bye!\n");
1692 VG_(printf)("\n");
1693 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001694}
1695
njn25e49d8e72002-09-23 09:36:25 +00001696/* ---------------------------------------------------------------------
1697 Generally useful...
1698 ------------------------------------------------------------------ */
1699
1700Int VG_(log2) ( Int x )
1701{
1702 Int i;
1703 /* Any more than 32 and we overflow anyway... */
1704 for (i = 0; i < 32; i++) {
1705 if (1 << i == x) return i;
1706 }
1707 return -1;
1708}
1709
1710
njnd3b0c5f2003-09-30 14:43:54 +00001711// Generic shell sort. Like stdlib.h's qsort().
1712void VG_(ssort)( void* base, UInt nmemb, UInt size,
1713 Int (*compar)(void*, void*) )
1714{
1715 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1716 9841, 29524, 88573, 265720,
1717 797161, 2391484 };
1718 Int lo = 0;
1719 Int hi = nmemb-1;
1720 Int i, j, h, bigN, hp;
1721
1722 bigN = hi - lo + 1; if (bigN < 2) return;
1723 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1724 vg_assert(0 <= hp && hp < 14);
1725
1726 #define SORT \
1727 for ( ; hp >= 0; hp--) { \
1728 h = incs[hp]; \
njn92c54362003-10-15 14:00:35 +00001729 for (i = lo + h; i <= hi; i++) { \
njnd3b0c5f2003-09-30 14:43:54 +00001730 ASSIGN(v,0, a,i); \
1731 j = i; \
njn92c54362003-10-15 14:00:35 +00001732 while (COMPAR(a,(j-h), v,0) > 0) { \
njnd3b0c5f2003-09-30 14:43:54 +00001733 ASSIGN(a,j, a,(j-h)); \
1734 j = j - h; \
1735 if (j <= (lo + h - 1)) break; \
1736 } \
1737 ASSIGN(a,j, v,0); \
njnd3b0c5f2003-09-30 14:43:54 +00001738 } \
1739 }
1740
1741 // Specialised cases
1742 if (sizeof(UInt) == size) {
1743
1744 #define ASSIGN(dst, dsti, src, srci) \
1745 (dst)[(dsti)] = (src)[(srci)];
1746
1747 #define COMPAR(dst, dsti, src, srci) \
1748 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1749
1750 UInt* a = (UInt*)base;
1751 UInt v[1];
1752
1753 SORT;
1754
1755 } else if (sizeof(UShort) == size) {
1756 UShort* a = (UShort*)base;
1757 UShort v[1];
1758
1759 SORT;
1760
1761 } else if (sizeof(UChar) == size) {
1762 UChar* a = (UChar*)base;
1763 UChar v[1];
1764
1765 SORT;
1766
1767 #undef ASSIGN
1768 #undef COMPAR
1769
1770 // General case
1771 } else {
njn92c54362003-10-15 14:00:35 +00001772 char* a = base;
1773 char v[size]; // will be at least 'size' bytes
njnd3b0c5f2003-09-30 14:43:54 +00001774
1775 #define ASSIGN(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001776 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
njnd3b0c5f2003-09-30 14:43:54 +00001777
1778 #define COMPAR(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001779 compar( &dst[size*(dsti)], &src[size*(srci)] )
njnd3b0c5f2003-09-30 14:43:54 +00001780
1781 SORT;
1782
1783 #undef ASSIGN
1784 #undef COMPAR
1785 }
1786 #undef SORT
1787}
1788
sewardj73cf3bc2002-11-03 03:20:15 +00001789/* ---------------------------------------------------------------------
1790 Gruesome hackery for connecting to a logging server over the network.
1791 This is all very Linux-kernel specific.
1792 ------------------------------------------------------------------ */
1793
1794/* Various needed constants from the kernel iface (2.4),
1795 /usr/src/linux-2.4.9-31 */
1796
1797/* kernel, ./include/linux/net.h */
rjwalshf5f536f2003-11-17 17:45:00 +00001798#define SYS_SOCKET 1 /* sys_socket(2) */
1799#define SYS_CONNECT 3 /* sys_connect(2) */
1800#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
1801#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
1802#define SYS_SEND 9 /* sys_send(2) */
1803#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
sewardj73cf3bc2002-11-03 03:20:15 +00001804
1805typedef UInt __u32;
1806
1807/* Internet address. */
1808struct vki_in_addr {
1809 __u32 s_addr;
1810};
1811
1812/* kernel, include/linux/socket.h */
sewardj73cf3bc2002-11-03 03:20:15 +00001813#define AF_INET 2 /* Internet IP Protocol */
sewardj570f8902002-11-03 11:44:36 +00001814#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
sewardj73cf3bc2002-11-03 03:20:15 +00001815
1816/* kernel, ./include/asm-i386/socket.h */
1817#define SOCK_STREAM 1 /* stream (connection) socket */
1818
1819/* kernel, /usr/src/linux-2.4.9-31/linux/include/in.h */
1820/* Structure describing an Internet (IP) socket address. */
1821#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
1822struct vki_sockaddr_in {
1823 vki_sa_family_t sin_family; /* Address family */
1824 unsigned short int sin_port; /* Port number */
1825 struct vki_in_addr sin_addr; /* Internet address */
1826
1827 /* Pad to size of `struct sockaddr'. */
1828 unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
1829 sizeof(unsigned short int) -
1830 sizeof(struct vki_in_addr)];
1831};
1832
1833
1834static
1835Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1836
1837static
1838Int my_socket ( Int domain, Int type, Int protocol );
1839
1840static
1841Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1842 Int addrlen );
1843
1844static
1845UInt my_htonl ( UInt x )
1846{
1847 return
1848 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1849 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1850}
1851
1852static
1853UShort my_htons ( UShort x )
1854{
1855 return
1856 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1857}
1858
1859
1860/* The main function.
1861
1862 Supplied string contains either an ip address "192.168.0.1" or
1863 an ip address and port pair, "192.168.0.1:1500". Parse these,
1864 and return:
1865 -1 if there is a parse error
1866 -2 if no parse error, but specified host:port cannot be opened
1867 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001868 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001869*/
1870Int VG_(connect_via_socket)( UChar* str )
1871{
1872 Int sd, res;
1873 struct vki_sockaddr_in servAddr;
1874 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001875 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001876 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1877 if (!ok)
1878 return -1;
1879
1880 if (0)
1881 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1882 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1883 (ip >> 8) & 0xFF, ip & 0xFF,
1884 (UInt)port );
1885
1886 servAddr.sin_family = AF_INET;
1887 servAddr.sin_addr.s_addr = my_htonl(ip);
1888 servAddr.sin_port = my_htons(port);
1889
1890 /* create socket */
1891 sd = my_socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1892 if (sd < 0) {
1893 /* this shouldn't happen ... nevertheless */
1894 return -2;
1895 }
1896
1897 /* connect to server */
1898 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1899 sizeof(servAddr));
1900 if (res < 0) {
1901 /* connection failed */
1902 return -2;
1903 }
1904
1905 return sd;
1906}
1907
1908
1909/* Let d = one or more digits. Accept either:
1910 d.d.d.d or d.d.d.d:d
1911*/
1912Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1913{
1914# define GET_CH ((*str) ? (*str++) : 0)
1915 UInt ipa, i, j, c, any;
1916 ipa = 0;
1917 for (i = 0; i < 4; i++) {
1918 j = 0;
1919 any = 0;
1920 while (1) {
1921 c = GET_CH;
1922 if (c < '0' || c > '9') break;
1923 j = 10 * j + (int)(c - '0');
1924 any = 1;
1925 }
1926 if (any == 0 || j > 255) goto syntaxerr;
1927 ipa = (ipa << 8) + j;
1928 if (i <= 2 && c != '.') goto syntaxerr;
1929 }
1930 if (c == 0 || c == ':')
1931 *ip_addr = ipa;
1932 if (c == 0) goto ok;
1933 if (c != ':') goto syntaxerr;
1934 j = 0;
1935 any = 0;
1936 while (1) {
1937 c = GET_CH;
1938 if (c < '0' || c > '9') break;
1939 j = j * 10 + (int)(c - '0');
1940 any = 1;
1941 if (j > 65535) goto syntaxerr;
1942 }
1943 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001944 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001945 *port = (UShort)j;
1946 ok:
1947 return 1;
1948 syntaxerr:
1949 return 0;
1950# undef GET_CH
1951}
1952
1953
1954static
1955Int my_socket ( Int domain, Int type, Int protocol )
1956{
1957 Int res;
1958 UInt args[3];
1959 args[0] = domain;
1960 args[1] = type;
1961 args[2] = protocol;
jsgf855d93d2003-10-13 22:26:55 +00001962 res = VG_(do_syscall)(__NR_socketcall, SYS_SOCKET, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001963 if (VG_(is_kerror)(res))
1964 res = -1;
1965 return res;
1966}
1967
1968static
1969Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1970 Int addrlen )
1971{
1972 Int res;
1973 UInt args[3];
1974 args[0] = sockfd;
1975 args[1] = (UInt)serv_addr;
1976 args[2] = addrlen;
jsgf855d93d2003-10-13 22:26:55 +00001977 res = VG_(do_syscall)(__NR_socketcall, SYS_CONNECT, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001978 if (VG_(is_kerror)(res))
1979 res = -1;
1980 return res;
1981}
1982
1983Int VG_(write_socket)( Int sd, void *msg, Int count )
1984{
1985 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001986
1987 /* Requests not to send SIGPIPE on errors on stream oriented
1988 sockets when the other end breaks the connection. The EPIPE
1989 error is still returned. */
1990 Int flags = MSG_NOSIGNAL;
1991
sewardj73cf3bc2002-11-03 03:20:15 +00001992 Int res;
1993 UInt args[4];
1994 args[0] = sd;
1995 args[1] = (UInt)msg;
1996 args[2] = count;
1997 args[3] = flags;
jsgf855d93d2003-10-13 22:26:55 +00001998 res = VG_(do_syscall)(__NR_socketcall, SYS_SEND, (UInt)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001999 if (VG_(is_kerror)(res))
2000 res = -1;
2001 return res;
2002}
2003
rjwalshf5f536f2003-11-17 17:45:00 +00002004Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
2005{
2006 Int res;
2007 UInt args[3];
2008 args[0] = sd;
2009 args[1] = (UInt)name;
2010 args[2] = (UInt)namelen;
2011 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKNAME, (UInt)&args);
2012 if(VG_(is_kerror)(res))
2013 res = -1;
2014 return res;
2015}
2016
2017Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
2018{
2019 Int res;
2020 UInt args[3];
2021 args[0] = sd;
2022 args[1] = (UInt)name;
2023 args[2] = (UInt)namelen;
2024 res = VG_(do_syscall)(__NR_socketcall, SYS_GETPEERNAME, (UInt)&args);
2025 if(VG_(is_kerror)(res))
2026 res = -1;
2027 return res;
2028}
2029
2030Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
2031 Int *optlen)
2032{
2033 Int res;
2034 UInt args[5];
2035 args[0] = sd;
2036 args[1] = (UInt)level;
2037 args[2] = (UInt)optname;
2038 args[3] = (UInt)optval;
2039 args[4] = (UInt)optlen;
2040 res = VG_(do_syscall)(__NR_socketcall, SYS_GETSOCKOPT, (UInt)&args);
2041 if(VG_(is_kerror)(res))
2042 res = -1;
2043 return res;
2044}
2045
sewardjde4a1d02002-03-22 01:27:54 +00002046
2047/*--------------------------------------------------------------------*/
2048/*--- end vg_mylibc.c ---*/
2049/*--------------------------------------------------------------------*/