blob: 9f474075ad443899f231c3c71485b73ac84bf8f1 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Reimplementation of some C library stuff, to avoid depending ---*/
4/*--- on libc.so. ---*/
5/*--- vg_mylibc.c ---*/
6/*--------------------------------------------------------------------*/
7
8/*
njnc9539842002-10-02 13:26:35 +00009 This file is part of Valgrind, an extensible x86 protected-mode
10 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000011
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000013 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000014
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
njn25e49d8e72002-09-23 09:36:25 +000030 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000031*/
32
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000034
sewardjde4a1d02002-03-22 01:27:54 +000035/* ---------------------------------------------------------------------
36 Wrappers around system calls, and other stuff, to do with signals.
37 ------------------------------------------------------------------ */
38
39/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
40 success and -1 on error.
41*/
nethercote73b526f2004-10-31 18:48:21 +000042Int VG_(sigfillset)( vki_sigset_t* set )
sewardjde4a1d02002-03-22 01:27:54 +000043{
44 Int i;
45 if (set == NULL)
46 return -1;
nethercote73b526f2004-10-31 18:48:21 +000047 for (i = 0; i < _VKI_NSIG_WORDS; i++)
nethercoteacac2fd2004-11-04 13:49:28 +000048 set->sig[i] = ~(UWord)0x0;
sewardjde4a1d02002-03-22 01:27:54 +000049 return 0;
50}
51
nethercote73b526f2004-10-31 18:48:21 +000052Int VG_(sigemptyset)( vki_sigset_t* set )
sewardjde4a1d02002-03-22 01:27:54 +000053{
54 Int i;
55 if (set == NULL)
56 return -1;
nethercote73b526f2004-10-31 18:48:21 +000057 for (i = 0; i < _VKI_NSIG_WORDS; i++)
58 set->sig[i] = 0x0;
sewardjde4a1d02002-03-22 01:27:54 +000059 return 0;
60}
61
nethercote73b526f2004-10-31 18:48:21 +000062Bool VG_(isemptysigset)( vki_sigset_t* set )
sewardjb48e5002002-05-13 00:16:03 +000063{
64 Int i;
65 vg_assert(set != NULL);
nethercote73b526f2004-10-31 18:48:21 +000066 for (i = 0; i < _VKI_NSIG_WORDS; i++)
67 if (set->sig[i] != 0x0) return False;
sewardjb48e5002002-05-13 00:16:03 +000068 return True;
69}
70
nethercote73b526f2004-10-31 18:48:21 +000071Bool VG_(isfullsigset)( vki_sigset_t* set )
sewardj018f7622002-05-15 21:13:39 +000072{
73 Int i;
74 vg_assert(set != NULL);
nethercote73b526f2004-10-31 18:48:21 +000075 for (i = 0; i < _VKI_NSIG_WORDS; i++)
nethercote93246cf2004-11-04 18:56:47 +000076 if (set->sig[i] != ~(UWord)0x0) return False;
sewardj018f7622002-05-15 21:13:39 +000077 return True;
78}
79
80
nethercote73b526f2004-10-31 18:48:21 +000081Int VG_(sigaddset)( vki_sigset_t* set, Int signum )
sewardjde4a1d02002-03-22 01:27:54 +000082{
83 if (set == NULL)
84 return -1;
nethercote73b526f2004-10-31 18:48:21 +000085 if (signum < 1 || signum > _VKI_NSIG)
sewardjde4a1d02002-03-22 01:27:54 +000086 return -1;
87 signum--;
nethercote73b526f2004-10-31 18:48:21 +000088 set->sig[signum / _VKI_NSIG_BPW] |= (1 << (signum % _VKI_NSIG_BPW));
sewardjde4a1d02002-03-22 01:27:54 +000089 return 0;
90}
91
nethercote73b526f2004-10-31 18:48:21 +000092Int VG_(sigdelset)( vki_sigset_t* set, Int signum )
sewardj018f7622002-05-15 21:13:39 +000093{
94 if (set == NULL)
95 return -1;
nethercote73b526f2004-10-31 18:48:21 +000096 if (signum < 1 || signum > _VKI_NSIG)
sewardj018f7622002-05-15 21:13:39 +000097 return -1;
98 signum--;
nethercote73b526f2004-10-31 18:48:21 +000099 set->sig[signum / _VKI_NSIG_BPW] &= ~(1 << (signum % _VKI_NSIG_BPW));
sewardj018f7622002-05-15 21:13:39 +0000100 return 0;
101}
102
nethercote73b526f2004-10-31 18:48:21 +0000103Int VG_(sigismember) ( vki_sigset_t* set, Int signum )
sewardjde4a1d02002-03-22 01:27:54 +0000104{
105 if (set == NULL)
sewardjb48e5002002-05-13 00:16:03 +0000106 return 0;
nethercote73b526f2004-10-31 18:48:21 +0000107 if (signum < 1 || signum > _VKI_NSIG)
sewardjb48e5002002-05-13 00:16:03 +0000108 return 0;
sewardjde4a1d02002-03-22 01:27:54 +0000109 signum--;
nethercote73b526f2004-10-31 18:48:21 +0000110 if (1 & ((set->sig[signum / _VKI_NSIG_BPW]) >> (signum % _VKI_NSIG_BPW)))
sewardjde4a1d02002-03-22 01:27:54 +0000111 return 1;
112 else
113 return 0;
114}
115
116
sewardjb48e5002002-05-13 00:16:03 +0000117/* Add all signals in src to dst. */
nethercote73b526f2004-10-31 18:48:21 +0000118void VG_(sigaddset_from_set)( vki_sigset_t* dst, vki_sigset_t* src )
sewardjb48e5002002-05-13 00:16:03 +0000119{
120 Int i;
121 vg_assert(dst != NULL && src != NULL);
nethercote73b526f2004-10-31 18:48:21 +0000122 for (i = 0; i < _VKI_NSIG_WORDS; i++)
123 dst->sig[i] |= src->sig[i];
sewardjb48e5002002-05-13 00:16:03 +0000124}
125
126/* Remove all signals in src from dst. */
nethercote73b526f2004-10-31 18:48:21 +0000127void VG_(sigdelset_from_set)( vki_sigset_t* dst, vki_sigset_t* src )
sewardjb48e5002002-05-13 00:16:03 +0000128{
129 Int i;
130 vg_assert(dst != NULL && src != NULL);
nethercote73b526f2004-10-31 18:48:21 +0000131 for (i = 0; i < _VKI_NSIG_WORDS; i++)
132 dst->sig[i] &= ~(src->sig[i]);
sewardjb48e5002002-05-13 00:16:03 +0000133}
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*/
nethercote50397c22004-11-04 18:03:06 +0000139Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset)
sewardjde4a1d02002-03-22 01:27:54 +0000140{
141 Int res
jsgf855d93d2003-10-13 22:26:55 +0000142 = VG_(do_syscall)(__NR_rt_sigprocmask,
nethercote50397c22004-11-04 18:03:06 +0000143 how, (UWord)set, (UWord)oldset,
nethercote73b526f2004-10-31 18:48:21 +0000144 _VKI_NSIG_WORDS * sizeof(UWord));
sewardjde4a1d02002-03-22 01:27:54 +0000145 return VG_(is_kerror)(res) ? -1 : 0;
146}
147
148
nethercote50397c22004-11-04 18:03:06 +0000149Int VG_(sigaction) ( Int signum, const struct vki_sigaction* act,
150 struct vki_sigaction* oldact)
sewardjde4a1d02002-03-22 01:27:54 +0000151{
152 Int res
jsgf855d93d2003-10-13 22:26:55 +0000153 = VG_(do_syscall)(__NR_rt_sigaction,
nethercote50397c22004-11-04 18:03:06 +0000154 signum, (UWord)act, (UWord)oldact,
nethercote73b526f2004-10-31 18:48:21 +0000155 _VKI_NSIG_WORDS * sizeof(UWord));
sewardj018f7622002-05-15 21:13:39 +0000156 /* VG_(printf)("res = %d\n",res); */
sewardjde4a1d02002-03-22 01:27:54 +0000157 return VG_(is_kerror)(res) ? -1 : 0;
158}
159
160
nethercote73b526f2004-10-31 18:48:21 +0000161Int VG_(sigaltstack)( const vki_stack_t* ss, vki_stack_t* oss )
sewardjde4a1d02002-03-22 01:27:54 +0000162{
nethercotefbd6ffd2004-11-04 17:10:24 +0000163 Int res = VG_(do_syscall)(__NR_sigaltstack, (UWord)ss, (UWord)oss);
sewardjde4a1d02002-03-22 01:27:54 +0000164 return VG_(is_kerror)(res) ? -1 : 0;
165}
166
nethercote73b526f2004-10-31 18:48:21 +0000167Int VG_(sigtimedwait)( const vki_sigset_t *set, vki_siginfo_t *info,
jsgf855d93d2003-10-13 22:26:55 +0000168 const struct vki_timespec *timeout )
169{
170 Int res = VG_(do_syscall)(__NR_rt_sigtimedwait, set, info, timeout, sizeof(*set));
171
172 return VG_(is_kerror)(res) ? -1 : res;
173}
sewardjde4a1d02002-03-22 01:27:54 +0000174
nethercote73b526f2004-10-31 18:48:21 +0000175Int VG_(signal)(Int signum, void (*sighandler)(Int))
sewardjde4a1d02002-03-22 01:27:54 +0000176{
177 Int res;
nethercote73b526f2004-10-31 18:48:21 +0000178 struct vki_sigaction sa;
sewardjde4a1d02002-03-22 01:27:54 +0000179 sa.ksa_handler = sighandler;
nethercote73b526f2004-10-31 18:48:21 +0000180 sa.sa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
181 sa.sa_restorer = NULL;
182 res = VG_(sigemptyset)( &sa.sa_mask );
sewardjde4a1d02002-03-22 01:27:54 +0000183 vg_assert(res == 0);
jsgf855d93d2003-10-13 22:26:55 +0000184 res = VG_(do_syscall)(__NR_rt_sigaction,
nethercote50397c22004-11-04 18:03:06 +0000185 signum, (UWord)&sa, (UWord)NULL,
nethercote73b526f2004-10-31 18:48:21 +0000186 _VKI_NSIG_WORDS * sizeof(UWord));
sewardjde4a1d02002-03-22 01:27:54 +0000187 return VG_(is_kerror)(res) ? -1 : 0;
188}
189
190
nethercote73b526f2004-10-31 18:48:21 +0000191Int VG_(kill)( Int pid, Int signo )
sewardj018f7622002-05-15 21:13:39 +0000192{
jsgf855d93d2003-10-13 22:26:55 +0000193 Int res = VG_(do_syscall)(__NR_kill, pid, signo);
sewardj018f7622002-05-15 21:13:39 +0000194 return VG_(is_kerror)(res) ? -1 : 0;
195}
196
197
nethercote73b526f2004-10-31 18:48:21 +0000198Int VG_(tkill)( Int tid, Int signo )
jsgf855d93d2003-10-13 22:26:55 +0000199{
200 Int ret = -VKI_ENOSYS;
201
thughes848907a2004-10-18 18:56:25 +0000202#ifdef __NR_tgkill
203 ret = VG_(do_syscall)(__NR_tgkill, VG_(main_pid), tid, signo);
204#endif /* __NR_tgkill */
205
jsgf855d93d2003-10-13 22:26:55 +0000206#ifdef __NR_tkill
thughes848907a2004-10-18 18:56:25 +0000207 if (ret == -VKI_ENOSYS)
208 ret = VG_(do_syscall)(__NR_tkill, tid, signo);
jsgf855d93d2003-10-13 22:26:55 +0000209#endif /* __NR_tkill */
210
211 if (ret == -VKI_ENOSYS)
212 ret = VG_(do_syscall)(__NR_kill, tid, signo);
213
214 return VG_(is_kerror)(ret) ? -1 : 0;
215}
216
nethercote73b526f2004-10-31 18:48:21 +0000217Int VG_(sigpending) ( vki_sigset_t* set )
sewardjefbfcdf2002-06-19 17:35:45 +0000218{
nethercotecf51cc42004-11-04 17:02:42 +0000219 Int res = VG_(do_syscall)(__NR_sigpending, (UWord)set);
sewardjefbfcdf2002-06-19 17:35:45 +0000220 return VG_(is_kerror)(res) ? -1 : 0;
221}
222
jsgf855d93d2003-10-13 22:26:55 +0000223Int VG_(waitpid)(Int pid, Int *status, Int options)
224{
225 Int ret = VG_(do_syscall)(__NR_wait4, pid, status, options, NULL);
226
227 return VG_(is_kerror)(ret) ? -1 : ret;
228}
229
230Int VG_(gettid)(void)
231{
232 Int ret;
233
234 ret = VG_(do_syscall)(__NR_gettid);
235
thughes8ef6d962004-10-16 10:46:01 +0000236 if (ret == -VKI_ENOSYS) {
237 Char pid[16];
238
239 /*
240 * The gettid system call does not exist. The obvious assumption
241 * to make at this point would be that we are running on an older
242 * system where the getpid system call actually returns the ID of
243 * the current thread.
244 *
245 * Unfortunately it seems that there are some systems with a kernel
246 * where getpid has been changed to return the ID of the thread group
247 * leader but where the gettid system call has not yet been added.
248 *
249 * So instead of calling getpid here we use readlink to see where
250 * the /proc/self link is pointing...
251 */
252 if ((ret = VG_(do_syscall)(__NR_readlink, "/proc/self", pid, sizeof(pid))) >= 0) {
253 pid[ret] = '\0';
254 ret = VG_(atoll)(pid);
255 }
256 }
jsgf855d93d2003-10-13 22:26:55 +0000257
258 return ret;
259}
260
261
sewardjefbfcdf2002-06-19 17:35:45 +0000262
sewardjde4a1d02002-03-22 01:27:54 +0000263/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000264 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000265 ------------------------------------------------------------------ */
266
nethercotecf51cc42004-11-04 17:02:42 +0000267static Int munmap_inner(void *start, SizeT length)
fitzhardingeb50068f2004-02-24 23:42:55 +0000268{
nethercotecf51cc42004-11-04 17:02:42 +0000269 return VG_(do_syscall)(__NR_munmap, (UWord)start, length );
fitzhardingeb50068f2004-02-24 23:42:55 +0000270}
271
nethercote5b9fafd2004-11-04 18:39:22 +0000272static Addr mmap_inner(void *start, SizeT length, UInt prot, UInt flags,
273 UInt fd, OffT offset)
fitzhardingeb50068f2004-02-24 23:42:55 +0000274{
nethercote6456ab12004-10-18 14:47:48 +0000275 Int ret;
276
277 PLATFORM_DO_MMAP(ret, start, length, prot,
278 flags & ~(VKI_MAP_NOSYMS|VKI_MAP_CLIENT),
279 fd, offset);
280 return ret;
fitzhardingeb50068f2004-02-24 23:42:55 +0000281}
282
sewardjde4a1d02002-03-22 01:27:54 +0000283/* Returns -1 on failure. */
nethercote8b5f40c2004-11-02 13:29:50 +0000284void* VG_(mmap)( void* start, SizeT length,
nethercote5b9fafd2004-11-04 18:39:22 +0000285 UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset)
sewardjde4a1d02002-03-22 01:27:54 +0000286{
fitzhardinge98abfc72003-12-16 02:05:15 +0000287 Addr res;
fitzhardinge98abfc72003-12-16 02:05:15 +0000288
289 if (!(flags & VKI_MAP_FIXED)) {
290 start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
fitzhardinge98abfc72003-12-16 02:05:15 +0000291
292 flags |= VKI_MAP_FIXED;
293 }
nethercoteb4250ae2004-07-10 16:50:09 +0000294 if (start == 0)
295 return (void *)-1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000296
fitzhardingeb50068f2004-02-24 23:42:55 +0000297 res = mmap_inner(start, length, prot, flags, fd, offset);
fitzhardinge98abfc72003-12-16 02:05:15 +0000298
nethercoteb4250ae2004-07-10 16:50:09 +0000299 // Check it ended up in the right place.
fitzhardinge98abfc72003-12-16 02:05:15 +0000300 if (!VG_(is_kerror)(res)) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000301 if (flags & VKI_MAP_CLIENT) {
nethercote00600502004-09-11 23:27:09 +0000302 vg_assert(VG_(client_base) <= res && res+length <= VG_(client_end));
fitzhardinge98abfc72003-12-16 02:05:15 +0000303 } else {
nethercotefb583e22004-09-07 23:15:37 +0000304 vg_assert(VG_(valgrind_base) <= res && res+length-1 <= VG_(valgrind_last));
fitzhardinge98abfc72003-12-16 02:05:15 +0000305 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000306
nethercoteb4250ae2004-07-10 16:50:09 +0000307 sf_flags |= SF_MMAP;
308 if ( flags & VKI_MAP_FIXED) sf_flags |= SF_FIXED;
309 if ( flags & VKI_MAP_SHARED) sf_flags |= SF_SHARED;
310 if (!(flags & VKI_MAP_ANONYMOUS)) sf_flags |= SF_FILE;
311 if (!(flags & VKI_MAP_CLIENT)) sf_flags |= SF_VALGRIND;
312 if ( flags & VKI_MAP_NOSYMS) sf_flags |= SF_NOSYMS;
313
314 VG_(map_fd_segment)(res, length, prot, sf_flags, fd, offset, NULL);
315 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000316
sewardjde4a1d02002-03-22 01:27:54 +0000317 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
318}
319
320/* Returns -1 on failure. */
nethercote8b5f40c2004-11-02 13:29:50 +0000321Int VG_(munmap)( void* start, SizeT length )
sewardjde4a1d02002-03-22 01:27:54 +0000322{
fitzhardingeb50068f2004-02-24 23:42:55 +0000323 Int res = munmap_inner(start, length);
fitzhardinge920d04e2003-12-20 18:19:50 +0000324 if (!VG_(is_kerror)(res))
fitzhardinge98abfc72003-12-16 02:05:15 +0000325 VG_(unmap_range)((Addr)start, length);
326 return VG_(is_kerror)(res) ? -1 : 0;
327}
328
nethercote8b5f40c2004-11-02 13:29:50 +0000329Int VG_(mprotect)( void *start, SizeT length, UInt prot )
fitzhardinge98abfc72003-12-16 02:05:15 +0000330{
nethercote8b5f40c2004-11-02 13:29:50 +0000331 Int res = VG_(do_syscall)(__NR_mprotect, (UWord)start, length, prot );
fitzhardinge98abfc72003-12-16 02:05:15 +0000332 if (!VG_(is_kerror)(res))
333 VG_(mprotect_range)((Addr)start, length, prot);
sewardjde4a1d02002-03-22 01:27:54 +0000334 return VG_(is_kerror)(res) ? -1 : 0;
335}
336
337void VG_(exit)( Int status )
338{
nethercotecf51cc42004-11-04 17:02:42 +0000339 (void)VG_(do_syscall)(__NR_exit_group, status );
340 (void)VG_(do_syscall)(__NR_exit, status );
sewardjde4a1d02002-03-22 01:27:54 +0000341 /* Why are we still alive here? */
342 /*NOTREACHED*/
jsgf855d93d2003-10-13 22:26:55 +0000343 *(volatile Int *)0 = 'x';
sewardjde4a1d02002-03-22 01:27:54 +0000344 vg_assert(2+2 == 5);
345}
346
sewardj2e93c502002-04-12 11:12:52 +0000347/* Returns -1 on error. */
348Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
349{
jsgf855d93d2003-10-13 22:26:55 +0000350 Int res = VG_(do_syscall)(__NR_fcntl, fd, cmd, arg);
sewardj2e93c502002-04-12 11:12:52 +0000351 return VG_(is_kerror)(res) ? -1 : res;
352}
353
jsgf855d93d2003-10-13 22:26:55 +0000354Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
355{
356 Int res = VG_(do_syscall)(__NR_poll, ufds, nfds, timeout);
357
358 return res;
359}
360
sewardj2e93c502002-04-12 11:12:52 +0000361
sewardjde4a1d02002-03-22 01:27:54 +0000362/* ---------------------------------------------------------------------
363 printf implementation. The key function, vg_vprintf(), emits chars
364 into a caller-supplied function. Distantly derived from:
365
366 vprintf replacement for Checker.
367 Copyright 1993, 1994, 1995 Tristan Gingold
368 Written September 1993 Tristan Gingold
369 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
370
371 (Checker itself was GPL'd.)
372 ------------------------------------------------------------------ */
373
374
375/* Some flags. */
376#define VG_MSG_SIGNED 1 /* The value is signed. */
377#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
378#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
sewardj78e3cd92002-10-22 04:45:48 +0000379#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
njn607adfc2003-09-30 14:15:44 +0000380#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
sewardjde4a1d02002-03-22 01:27:54 +0000381
382/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000383static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000384myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
385 Bool capitalise )
386{
387# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000388 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000389 Int i, extra;
390 Int len = VG_(strlen)(str);
391
392 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000393 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000394 for (i = 0; i < len; i++)
395 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000396 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000397 }
398
399 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000400 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000401 for (i = 0; i < width; i++)
402 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000403 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000404 }
405
406 extra = width - len;
407 if (flags & VG_MSG_LJUSTIFY) {
sewardj78e3cd92002-10-22 04:45:48 +0000408 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000409 for (i = 0; i < extra; i++)
410 send(' ');
411 }
sewardj78e3cd92002-10-22 04:45:48 +0000412 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000413 for (i = 0; i < len; i++)
414 send(MAYBE_TOUPPER(str[i]));
415 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000416 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000417 for (i = 0; i < extra; i++)
418 send(' ');
419 }
420
421# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000422
423 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000424}
425
426/* Write P into the buffer according to these args:
427 * If SIGN is true, p is a signed.
428 * BASE is the base.
429 * If WITH_ZERO is true, '0' must be added.
430 * WIDTH is the width of the field.
431 */
sewardj78e3cd92002-10-22 04:45:48 +0000432static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000433myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
434{
435 Char buf[40];
436 Int ind = 0;
njn607adfc2003-09-30 14:15:44 +0000437 Int i, nc = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000438 Bool neg = False;
439 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000440 UInt ret = 0;
441
sewardjde4a1d02002-03-22 01:27:54 +0000442 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000443 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000444
445 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
446 p = - (Long)p;
447 neg = True;
448 }
449
450 if (p == 0)
451 buf[ind++] = '0';
452 else {
453 while (p > 0) {
njn607adfc2003-09-30 14:15:44 +0000454 if (flags & VG_MSG_COMMA && 10 == base &&
455 0 == (ind-nc) % 3 && 0 != ind)
456 {
457 buf[ind++] = ',';
458 nc++;
459 }
sewardjde4a1d02002-03-22 01:27:54 +0000460 buf[ind++] = digits[p % base];
461 p /= base;
njn607adfc2003-09-30 14:15:44 +0000462 }
sewardjde4a1d02002-03-22 01:27:54 +0000463 }
464
465 if (neg)
466 buf[ind++] = '-';
467
468 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
469 for(; ind < width; ind++) {
470 vg_assert(ind < 39);
471 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
472 }
473 }
474
475 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000476 ret += ind;
njn607adfc2003-09-30 14:15:44 +0000477 for (i = ind -1; i >= 0; i--) {
sewardjde4a1d02002-03-22 01:27:54 +0000478 send(buf[i]);
njn607adfc2003-09-30 14:15:44 +0000479 }
sewardjde4a1d02002-03-22 01:27:54 +0000480 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000481 for(; ind < width; ind++) {
482 ret++;
njn607adfc2003-09-30 14:15:44 +0000483 send(' '); // Never pad with zeroes on RHS -- changes the value!
sewardj78e3cd92002-10-22 04:45:48 +0000484 }
sewardjde4a1d02002-03-22 01:27:54 +0000485 }
sewardj78e3cd92002-10-22 04:45:48 +0000486 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000487}
488
489
490/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000491UInt
sewardjde4a1d02002-03-22 01:27:54 +0000492VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
493{
sewardj78e3cd92002-10-22 04:45:48 +0000494 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000495 int i;
496 int flags;
497 int width;
498 Bool is_long;
499
500 /* We assume that vargs has already been initialised by the
501 caller, using va_start, and that the caller will similarly
502 clean up with va_end.
503 */
504
505 for (i = 0; format[i] != 0; i++) {
506 if (format[i] != '%') {
507 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000508 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000509 continue;
510 }
511 i++;
512 /* A '%' has been found. Ignore a trailing %. */
513 if (format[i] == 0)
514 break;
515 if (format[i] == '%') {
516 /* `%%' is replaced by `%'. */
517 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000518 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000519 continue;
520 }
521 flags = 0;
522 is_long = False;
523 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000524 if (format[i] == '(') {
525 flags |= VG_MSG_PAREN;
526 i++;
527 }
njn607adfc2003-09-30 14:15:44 +0000528 /* If ',' follows '%', commas will be inserted. */
529 if (format[i] == ',') {
530 flags |= VG_MSG_COMMA;
531 i++;
532 }
sewardjde4a1d02002-03-22 01:27:54 +0000533 /* If '-' follows '%', justify on the left. */
534 if (format[i] == '-') {
535 flags |= VG_MSG_LJUSTIFY;
536 i++;
537 }
538 /* If '0' follows '%', pads will be inserted. */
539 if (format[i] == '0') {
540 flags |= VG_MSG_ZJUSTIFY;
541 i++;
542 }
543 /* Compute the field length. */
544 while (format[i] >= '0' && format[i] <= '9') {
545 width *= 10;
546 width += format[i++] - '0';
547 }
548 while (format[i] == 'l') {
549 i++;
550 is_long = True;
551 }
552
553 switch (format[i]) {
554 case 'd': /* %d */
555 flags |= VG_MSG_SIGNED;
556 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000557 ret += myvprintf_int64(send, flags, 10, width,
558 (ULong)(va_arg (vargs, Long)));
sewardjde4a1d02002-03-22 01:27:54 +0000559 else
sewardj78e3cd92002-10-22 04:45:48 +0000560 ret += myvprintf_int64(send, flags, 10, width,
561 (ULong)(va_arg (vargs, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000562 break;
563 case 'u': /* %u */
564 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000565 ret += myvprintf_int64(send, flags, 10, width,
566 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000567 else
sewardj78e3cd92002-10-22 04:45:48 +0000568 ret += myvprintf_int64(send, flags, 10, width,
569 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000570 break;
571 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000572 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000573 send('0');
574 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000575 ret += myvprintf_int64(send, flags, 16, width,
nethercote50397c22004-11-04 18:03:06 +0000576 (ULong)((UWord)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000577 break;
578 case 'x': /* %x */
579 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000580 ret += myvprintf_int64(send, flags, 16, width,
581 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000582 else
sewardj78e3cd92002-10-22 04:45:48 +0000583 ret += myvprintf_int64(send, flags, 16, width,
584 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000585 break;
586 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000587 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000588 send(va_arg (vargs, int));
589 break;
590 case 's': case 'S': { /* %s */
591 char *str = va_arg (vargs, char *);
592 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000593 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000594 break;
sewardj78e3cd92002-10-22 04:45:48 +0000595 }
596 case 'y': { /* %y - print symbol */
597 Char buf[100];
598 Char *cp = buf;
599 Addr a = va_arg(vargs, Addr);
600
601 if (flags & VG_MSG_PAREN)
602 *cp++ = '(';
sewardj6e008cb2002-12-15 13:11:39 +0000603 if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
sewardj78e3cd92002-10-22 04:45:48 +0000604 if (flags & VG_MSG_PAREN) {
605 cp += VG_(strlen)(cp);
606 *cp++ = ')';
607 *cp = '\0';
608 }
609 ret += myvprintf_str(send, flags, width, buf, 0);
610 }
611
612 break;
613 }
sewardjde4a1d02002-03-22 01:27:54 +0000614 default:
615 break;
616 }
617 }
sewardj78e3cd92002-10-22 04:45:48 +0000618 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000619}
620
621
622/* A general replacement for printf(). Note that only low-level
623 debugging info should be sent via here. The official route is to
624 to use vg_message(). This interface is deprecated.
625*/
626static char myprintf_buf[100];
627static int n_myprintf_buf;
628
629static void add_to_myprintf_buf ( Char c )
630{
631 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
nethercotef8548672004-06-21 12:42:35 +0000632 if (VG_(clo_log_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000633 VG_(send_bytes_to_logging_sink)(
634 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000635 }
sewardjde4a1d02002-03-22 01:27:54 +0000636 n_myprintf_buf = 0;
637 myprintf_buf[n_myprintf_buf] = 0;
638 }
639 myprintf_buf[n_myprintf_buf++] = c;
640 myprintf_buf[n_myprintf_buf] = 0;
641}
642
sewardj78e3cd92002-10-22 04:45:48 +0000643UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000644{
sewardj78e3cd92002-10-22 04:45:48 +0000645 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000646 va_list vargs;
647 va_start(vargs,format);
648
649 n_myprintf_buf = 0;
650 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000651 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000652
nethercotef8548672004-06-21 12:42:35 +0000653 if (n_myprintf_buf > 0 && VG_(clo_log_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000654 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000655 }
sewardjde4a1d02002-03-22 01:27:54 +0000656
657 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000658
659 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000660}
661
sewardjde4a1d02002-03-22 01:27:54 +0000662/* A general replacement for sprintf(). */
thughes4ad52d02004-06-27 17:37:21 +0000663
664static Char *vg_sprintf_ptr;
665
666static void add_to_vg_sprintf_buf ( Char c )
667{
668 *vg_sprintf_ptr++ = c;
669}
670
sewardj78e3cd92002-10-22 04:45:48 +0000671UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000672{
sewardj05bcdcb2003-05-18 10:05:38 +0000673 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000674 va_list vargs;
thughes4ad52d02004-06-27 17:37:21 +0000675
676 vg_sprintf_ptr = buf;
677
sewardjde4a1d02002-03-22 01:27:54 +0000678 va_start(vargs,format);
679
sewardj78e3cd92002-10-22 04:45:48 +0000680 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000681 add_to_vg_sprintf_buf(0);
682
683 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000684
685 vg_assert(VG_(strlen)(buf) == ret);
686 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000687}
688
689
690/* ---------------------------------------------------------------------
691 Misc str* functions.
692 ------------------------------------------------------------------ */
693
694Bool VG_(isspace) ( Char c )
695{
696 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
697}
698
njn7cf0bd32002-06-08 13:36:03 +0000699Bool VG_(isdigit) ( Char c )
700{
701 return (c >= '0' && c <= '9');
702}
sewardjde4a1d02002-03-22 01:27:54 +0000703
704Int VG_(strlen) ( const Char* str )
705{
706 Int i = 0;
707 while (str[i] != 0) i++;
708 return i;
709}
710
711
712Long VG_(atoll) ( Char* str )
713{
714 Bool neg = False;
715 Long n = 0;
716 if (*str == '-') { str++; neg = True; };
717 while (*str >= '0' && *str <= '9') {
718 n = 10*n + (Long)(*str - '0');
719 str++;
720 }
721 if (neg) n = -n;
722 return n;
723}
724
725
njn25e49d8e72002-09-23 09:36:25 +0000726Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000727{
728 Bool neg = False;
729 Long n = 0;
730 if (*str == '-') { str++; neg = True; };
731 while (True) {
732 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000733 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000734 }
735 else
njn25e49d8e72002-09-23 09:36:25 +0000736 if (*str >= 'A' && *str <= 'F') {
737 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000738 }
739 else
njn25e49d8e72002-09-23 09:36:25 +0000740 if (*str >= 'a' && *str <= 'f') {
741 n = 16*n + (Long)((*str - 'a') + 10);
742 }
743 else {
744 break;
745 }
746 str++;
747 }
748 if (neg) n = -n;
749 return n;
750}
751
752Long VG_(atoll36) ( UInt base, Char* str )
753{
754 Bool neg = False;
755 Long n = 0;
756 vg_assert(base >= 2 && base <= 36);
757 if (*str == '-') { str++; neg = True; };
758 while (True) {
sewardj05bcdcb2003-05-18 10:05:38 +0000759 if (*str >= '0'
760 && *str <= (Char)('9' - (10 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000761 n = base*n + (Long)(*str - '0');
762 }
763 else
sewardj05bcdcb2003-05-18 10:05:38 +0000764 if (base > 10 && *str >= 'A'
765 && *str <= (Char)('Z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000766 n = base*n + (Long)((*str - 'A') + 10);
767 }
768 else
sewardj05bcdcb2003-05-18 10:05:38 +0000769 if (base > 10 && *str >= 'a'
770 && *str <= (Char)('z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000771 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000772 }
773 else {
774 break;
775 }
776 str++;
777 }
778 if (neg) n = -n;
779 return n;
780}
781
782
sewardjde4a1d02002-03-22 01:27:54 +0000783Char* VG_(strcat) ( Char* dest, const Char* src )
784{
785 Char* dest_orig = dest;
786 while (*dest) dest++;
787 while (*src) *dest++ = *src++;
788 *dest = 0;
789 return dest_orig;
790}
791
792
793Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
794{
795 Char* dest_orig = dest;
796 while (*dest) dest++;
797 while (*src && n > 0) { *dest++ = *src++; n--; }
798 *dest = 0;
799 return dest_orig;
800}
801
802
803Char* VG_(strpbrk) ( const Char* s, const Char* accept )
804{
805 const Char* a;
806 while (*s) {
807 a = accept;
808 while (*a)
809 if (*a++ == *s)
810 return (Char *) s;
811 s++;
812 }
813 return NULL;
814}
815
816
817Char* VG_(strcpy) ( Char* dest, const Char* src )
818{
819 Char* dest_orig = dest;
820 while (*src) *dest++ = *src++;
821 *dest = 0;
822 return dest_orig;
823}
824
825
826/* Copy bytes, not overrunning the end of dest and always ensuring
827 zero termination. */
828void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
829{
830 Int i;
831 vg_assert(ndest > 0);
832 i = 0;
833 dest[i] = 0;
834 while (True) {
835 if (src[i] == 0) return;
836 if (i >= ndest-1) return;
837 dest[i] = src[i];
838 i++;
839 dest[i] = 0;
840 }
841}
842
843
njn25e49d8e72002-09-23 09:36:25 +0000844Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000845{
njn25e49d8e72002-09-23 09:36:25 +0000846 Int i = 0;
847 while (True) {
848 if (i >= ndest) return dest; /* reached limit */
849 dest[i] = src[i];
850 if (src[i++] == 0) {
851 /* reached NUL; pad rest with zeroes as required */
852 while (i < ndest) dest[i++] = 0;
853 return dest;
854 }
855 }
sewardjde4a1d02002-03-22 01:27:54 +0000856}
857
858
859Int VG_(strcmp) ( const Char* s1, const Char* s2 )
860{
861 while (True) {
862 if (*s1 == 0 && *s2 == 0) return 0;
863 if (*s1 == 0) return -1;
864 if (*s2 == 0) return 1;
865
866 if (*(UChar*)s1 < *(UChar*)s2) return -1;
867 if (*(UChar*)s1 > *(UChar*)s2) return 1;
868
869 s1++; s2++;
870 }
871}
872
873
874Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
875{
876 while (True) {
877 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
878 if (VG_(isspace)(*s1)) return -1;
879 if (VG_(isspace)(*s2)) return 1;
880
881 if (*(UChar*)s1 < *(UChar*)s2) return -1;
882 if (*(UChar*)s1 > *(UChar*)s2) return 1;
883
884 s1++; s2++;
885 }
886}
887
888
889Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
890{
891 Int n = 0;
892 while (True) {
893 if (n >= nmax) return 0;
894 if (*s1 == 0 && *s2 == 0) return 0;
895 if (*s1 == 0) return -1;
896 if (*s2 == 0) return 1;
897
898 if (*(UChar*)s1 < *(UChar*)s2) return -1;
899 if (*(UChar*)s1 > *(UChar*)s2) return 1;
900
901 s1++; s2++; n++;
902 }
903}
904
905
906Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
907{
908 Int n = 0;
909 while (True) {
910 if (n >= nmax) return 0;
911 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
912 if (VG_(isspace)(*s1)) return -1;
913 if (VG_(isspace)(*s2)) 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
923Char* VG_(strstr) ( const Char* haystack, Char* needle )
924{
sewardj3984b852002-05-12 03:00:17 +0000925 Int n;
926 if (haystack == NULL)
927 return NULL;
928 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000929 while (True) {
930 if (haystack[0] == 0)
931 return NULL;
932 if (VG_(strncmp)(haystack, needle, n) == 0)
933 return (Char*)haystack;
934 haystack++;
935 }
936}
937
938
939Char* VG_(strchr) ( const Char* s, Char c )
940{
941 while (True) {
942 if (*s == c) return (Char*)s;
943 if (*s == 0) return NULL;
944 s++;
945 }
946}
947
948
thughesc0b63de2004-06-13 09:55:22 +0000949Char* VG_(strrchr) ( const Char* s, Char c )
950{
951 Int n = VG_(strlen)(s);
952 while (--n > 0) {
953 if (s[n] == c) return (Char*)s + n;
954 }
955 return NULL;
956}
957
958
sewardj7ab2aca2002-10-20 19:40:32 +0000959void* VG_(memcpy) ( void *dest, const void *src, Int sz )
960{
961 const Char *s = (const Char *)src;
962 Char *d = (Char *)dest;
963 vg_assert(sz >= 0);
964
965 while (sz--)
966 *d++ = *s++;
967
968 return dest;
969}
970
971
972void* VG_(memset) ( void *dest, Int c, Int sz )
973{
974 Char *d = (Char *)dest;
975 vg_assert(sz >= 0);
976
977 while (sz--)
978 *d++ = c;
979
980 return dest;
981}
982
njn6d68e792003-02-24 10:49:08 +0000983Int VG_(memcmp) ( const void* s1, const void* s2, Int n )
984{
985 Int res;
njnfa4690b2003-02-24 21:43:05 +0000986 UChar a0;
987 UChar b0;
njn6d68e792003-02-24 10:49:08 +0000988 vg_assert(n >= 0);
989
990 while (n != 0) {
njnfa4690b2003-02-24 21:43:05 +0000991 a0 = ((UChar *) s1)[0];
992 b0 = ((UChar *) s2)[0];
njn6d68e792003-02-24 10:49:08 +0000993 s1 += 1;
994 s2 += 1;
995 res = a0 - b0;
996 if (res != 0)
997 return res;
998 n -= 1;
999 }
1000 return 0;
1001}
sewardj7ab2aca2002-10-20 19:40:32 +00001002
sewardjde4a1d02002-03-22 01:27:54 +00001003Char VG_(toupper) ( Char c )
1004{
1005 if (c >= 'a' && c <= 'z')
1006 return c + ('A' - 'a');
1007 else
1008 return c;
1009}
1010
1011
njn25e49d8e72002-09-23 09:36:25 +00001012/* Inline just for the wrapper VG_(strdup) below */
1013__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +00001014{
njn25e49d8e72002-09-23 09:36:25 +00001015 Int i;
fitzhardingea7728472003-12-16 01:48:38 +00001016 Int len;
1017 Char* res;
1018
1019 if (s == NULL)
1020 return NULL;
1021
1022 len = VG_(strlen)(s) + 1;
1023 res = VG_(arena_malloc) (aid, len);
1024
njn25e49d8e72002-09-23 09:36:25 +00001025 for (i = 0; i < len; i++)
1026 res[i] = s[i];
1027 return res;
sewardjde4a1d02002-03-22 01:27:54 +00001028}
1029
nethercote7cc9c232004-01-21 15:08:04 +00001030/* Wrapper to avoid exposing tools to ArenaId's */
njn25e49d8e72002-09-23 09:36:25 +00001031Char* VG_(strdup) ( const Char* s )
1032{
nethercote60f5b822004-01-26 17:24:42 +00001033 return VG_(arena_strdup) ( VG_AR_TOOL, s );
njn25e49d8e72002-09-23 09:36:25 +00001034}
sewardjde4a1d02002-03-22 01:27:54 +00001035
1036/* ---------------------------------------------------------------------
1037 A simple string matching routine, purloined from Hugs98.
1038 `*' matches any sequence of zero or more characters
1039 `?' matches any single character exactly
1040 `\c' matches the character c only (ignoring special chars)
1041 c matches the character c only
1042 ------------------------------------------------------------------ */
1043
1044/* Keep track of recursion depth. */
1045static Int recDepth;
1046
fitzhardinge98abfc72003-12-16 02:05:15 +00001047static Bool string_match_wrk ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001048{
sewardje54b69d2003-07-06 01:14:42 +00001049 vg_assert(recDepth >= 0 && recDepth < 500);
sewardjde4a1d02002-03-22 01:27:54 +00001050 recDepth++;
1051 for (;;) {
1052 switch (*pat) {
1053 case '\0' : return (*str=='\0');
1054 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001055 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001056 recDepth--;
1057 return True;
1058 }
1059 } while (*str++);
1060 recDepth--;
1061 return False;
1062 case '?' : if (*str++=='\0') {
1063 recDepth--;
1064 return False;
1065 }
1066 pat++;
1067 break;
1068 case '\\' : if (*++pat == '\0') {
1069 recDepth--;
1070 return False; /* spurious trailing \ in pattern */
1071 }
1072 /* falls through to ... */
1073 default : if (*pat++ != *str++) {
1074 recDepth--;
1075 return False;
1076 }
1077 break;
1078 }
1079 }
1080}
1081
fitzhardinge98abfc72003-12-16 02:05:15 +00001082Bool VG_(string_match) ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001083{
1084 Bool b;
1085 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001086 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001087 /*
1088 VG_(printf)("%s %s %s\n",
1089 b?"TRUE ":"FALSE", pat, str);
1090 */
1091 return b;
1092}
1093
1094
1095/* ---------------------------------------------------------------------
1096 Assertery.
1097 ------------------------------------------------------------------ */
1098
jsgf855d93d2003-10-13 22:26:55 +00001099/* Fake up an ExeContext which is of our actual real CPU state, so we
1100 can print a stack trace. This isn't terribly useful in the case
1101 where we were killed by a signal, since we just get a backtrace
1102 into the signal handler. Also, it could be somewhat risky if we
1103 actully got the panic/exception within the execontext/stack
1104 dump/symtab code. But it's better than nothing. */
1105static inline ExeContext *get_real_execontext(Addr ret)
1106{
1107 ExeContext *ec;
nethercote856e5872004-10-25 20:44:09 +00001108 Addr sp, fp;
nethercote759dda32004-08-07 18:16:56 +00001109 Addr stacktop, sigstack_low, sigstack_high;
jsgf855d93d2003-10-13 22:26:55 +00001110
nethercote856e5872004-10-25 20:44:09 +00001111 ARCH_GET_REAL_STACK_PTR(sp);
1112 ARCH_GET_REAL_FRAME_PTR(fp);
nethercote820bd8c2004-09-07 23:04:49 +00001113 stacktop = VG_(valgrind_last);
nethercote759dda32004-08-07 18:16:56 +00001114 VG_(get_sigstack_bounds)( &sigstack_low, &sigstack_high );
nethercote856e5872004-10-25 20:44:09 +00001115 if (sp >= sigstack_low && sp < sigstack_high)
nethercote759dda32004-08-07 18:16:56 +00001116 stacktop = sigstack_high;
jsgf855d93d2003-10-13 22:26:55 +00001117
nethercote856e5872004-10-25 20:44:09 +00001118 ec = VG_(get_ExeContext2)(ret, fp, sp, stacktop);
jsgf855d93d2003-10-13 22:26:55 +00001119
1120 return ec;
1121}
1122
njne427a662002-10-02 11:08:25 +00001123__attribute__ ((noreturn))
thughes5876d552004-09-26 18:44:06 +00001124static void report_and_quit ( const Char* report, ExeContext *ec )
njne427a662002-10-02 11:08:25 +00001125{
thughes5876d552004-09-26 18:44:06 +00001126 if (ec == NULL)
1127 ec = get_real_execontext((Addr)__builtin_return_address(0));
1128
jsgf855d93d2003-10-13 22:26:55 +00001129 VG_(pp_ExeContext)(ec);
1130
njne427a662002-10-02 11:08:25 +00001131 VG_(pp_sched_status)();
sewardj366ee1e2003-04-26 22:36:42 +00001132 VG_(printf)("\n");
1133 VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
1134 VG_(printf)("It contains workarounds to several common problems.\n");
1135 VG_(printf)("\n");
1136 VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
1137 report);
1138 VG_(printf)("In the bug report, send all the above text, the valgrind\n");
sewardj96330bd2003-04-27 23:46:21 +00001139 VG_(printf)("version, and what Linux distro you are using. Thanks.\n\n");
njne427a662002-10-02 11:08:25 +00001140 VG_(exit)(1);
1141}
1142
1143__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001144static void assert_fail ( const Char* expr, const Char* name, const Char* report,
1145 const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001146{
sewardj018f7622002-05-15 21:13:39 +00001147 static Bool entered = False;
1148 if (entered)
1149 VG_(exit)(2);
1150 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001151 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001152 name, file, line, fn, expr );
thughes5876d552004-09-26 18:44:06 +00001153 report_and_quit(report, NULL);
sewardjde4a1d02002-03-22 01:27:54 +00001154}
1155
njn94065fd2004-11-22 19:26:27 +00001156void VG_(tool_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001157{
njnd04b7c62002-10-03 14:05:52 +00001158 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001159 file, line, fn);
1160}
1161
daywalker3222e0a2003-09-18 01:39:50 +00001162void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
njne427a662002-10-02 11:08:25 +00001163{
nethercote421281e2003-11-20 16:20:55 +00001164 assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn);
njne427a662002-10-02 11:08:25 +00001165}
1166
1167__attribute__ ((noreturn))
thughes671ce382004-09-27 18:57:08 +00001168static void panic ( Char* name, Char* report, Char* str, ExeContext *ec )
njne427a662002-10-02 11:08:25 +00001169{
1170 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001171 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
thughes671ce382004-09-27 18:57:08 +00001172 report_and_quit(report, ec);
sewardjde4a1d02002-03-22 01:27:54 +00001173}
1174
njne427a662002-10-02 11:08:25 +00001175void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001176{
thughes5876d552004-09-26 18:44:06 +00001177 panic("valgrind", VG_BUGS_TO, str, NULL);
1178}
1179
1180void VG_(core_panic_at) ( Char* str, ExeContext *ec )
1181{
1182 panic("valgrind", VG_BUGS_TO, str, ec);
njn25e49d8e72002-09-23 09:36:25 +00001183}
1184
njn67993252004-11-22 18:02:32 +00001185void VG_(tool_panic) ( Char* str )
njne427a662002-10-02 11:08:25 +00001186{
thughes5876d552004-09-26 18:44:06 +00001187 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njne427a662002-10-02 11:08:25 +00001188}
sewardjde4a1d02002-03-22 01:27:54 +00001189
njn13f02932003-04-30 20:23:58 +00001190
sewardjde4a1d02002-03-22 01:27:54 +00001191/* ---------------------------------------------------------------------
1192 Primitive support for reading files.
1193 ------------------------------------------------------------------ */
1194
jsgf855d93d2003-10-13 22:26:55 +00001195static inline Bool fd_exists(Int fd)
1196{
1197 struct vki_stat st;
1198
1199 return VG_(fstat)(fd, &st) == 0;
1200}
1201
1202/* Move an fd into the Valgrind-safe range */
1203Int VG_(safe_fd)(Int oldfd)
1204{
1205 Int newfd;
1206
thughesad1c9562004-06-26 11:27:52 +00001207 vg_assert(VG_(fd_hard_limit) != -1);
fitzhardingeb791a192003-12-18 07:22:44 +00001208
thughesad1c9562004-06-26 11:27:52 +00001209 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
jsgf855d93d2003-10-13 22:26:55 +00001210 if (newfd != -1)
1211 VG_(close)(oldfd);
1212
1213 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
1214
thughesad1c9562004-06-26 11:27:52 +00001215 vg_assert(newfd >= VG_(fd_hard_limit));
jsgf855d93d2003-10-13 22:26:55 +00001216 return newfd;
1217}
1218
1219
1220
sewardjde4a1d02002-03-22 01:27:54 +00001221/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001222Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1223{
sewardjde4a1d02002-03-22 01:27:54 +00001224 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001225
njn25e49d8e72002-09-23 09:36:25 +00001226 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001227 /* This gets a segmentation fault if pathname isn't a valid file.
1228 I don't know why. It seems like the call to open is getting
1229 intercepted and messed with by glibc ... */
1230 /* fd = open( pathname, O_RDONLY ); */
1231 /* ... so we go direct to the horse's mouth, which seems to work
1232 ok: */
nethercotecf51cc42004-11-04 17:02:42 +00001233 fd = VG_(do_syscall)(__NR_open, (UWord)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001234 /* VG_(printf)("result = %d\n", fd); */
jsgff3c3f1a2003-10-14 22:13:28 +00001235 /* return -ve error code */
njn4f9c9342002-04-29 16:03:24 +00001236 return fd;
1237}
sewardjde4a1d02002-03-22 01:27:54 +00001238
jsgf855d93d2003-10-13 22:26:55 +00001239Int VG_(pipe) ( Int fd[2] )
1240{
1241 Int ret = VG_(do_syscall)(__NR_pipe, fd);
1242 return VG_(is_kerror)(ret) ? -1 : 0;
1243}
1244
sewardjde4a1d02002-03-22 01:27:54 +00001245void VG_(close) ( Int fd )
1246{
jsgf855d93d2003-10-13 22:26:55 +00001247 VG_(do_syscall)(__NR_close, fd);
sewardjde4a1d02002-03-22 01:27:54 +00001248}
1249
1250
1251Int VG_(read) ( Int fd, void* buf, Int count)
1252{
1253 Int res;
1254 /* res = read( fd, buf, count ); */
nethercotecf51cc42004-11-04 17:02:42 +00001255 res = VG_(do_syscall)(__NR_read, fd, (UWord)buf, count);
jsgf855d93d2003-10-13 22:26:55 +00001256 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001257 return res;
1258}
1259
jsgf855d93d2003-10-13 22:26:55 +00001260Int VG_(write) ( Int fd, const void* buf, Int count)
sewardjde4a1d02002-03-22 01:27:54 +00001261{
1262 Int res;
1263 /* res = write( fd, buf, count ); */
nethercotecf51cc42004-11-04 17:02:42 +00001264 res = VG_(do_syscall)(__NR_write, fd, (UWord)buf, count);
jsgf855d93d2003-10-13 22:26:55 +00001265 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001266 return res;
1267}
1268
nethercote5b9fafd2004-11-04 18:39:22 +00001269OffT VG_(lseek) ( Int fd, OffT offset, Int whence)
rjwalshf5f536f2003-11-17 17:45:00 +00001270{
1271 Int res;
1272 /* res = lseek( fd, offset, whence ); */
nethercote5b9fafd2004-11-04 18:39:22 +00001273 res = VG_(do_syscall)(__NR_lseek, fd, offset, whence);
rjwalshf5f536f2003-11-17 17:45:00 +00001274 if (VG_(is_kerror)(res)) res = -1;
1275 return res;
1276}
1277
sewardjb3586202002-05-09 17:38:13 +00001278Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1279{
1280 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001281 res = VG_(do_syscall)(__NR_stat, (UWord)file_name, (UWord)buf);
fitzhardingee1c06d82003-10-30 07:21:44 +00001282 return res; /* return -ve error */
njn41557122002-10-14 09:25:37 +00001283}
1284
jsgf855d93d2003-10-13 22:26:55 +00001285Int VG_(fstat) ( Int fd, struct vki_stat* buf )
1286{
1287 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001288 res = VG_(do_syscall)(__NR_fstat, fd, (UWord)buf);
jsgf855d93d2003-10-13 22:26:55 +00001289 return VG_(is_kerror)(res) ? (-1) : 0;
1290}
1291
1292Int VG_(dup2) ( Int oldfd, Int newfd )
1293{
1294 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001295 res = VG_(do_syscall)(__NR_dup2, oldfd, newfd);
jsgf855d93d2003-10-13 22:26:55 +00001296 return VG_(is_kerror)(res) ? (-1) : res;
1297}
1298
njn41557122002-10-14 09:25:37 +00001299Int VG_(rename) ( Char* old_name, Char* new_name )
1300{
1301 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001302 res = VG_(do_syscall)(__NR_rename, (UWord)old_name, (UWord)new_name);
njn41557122002-10-14 09:25:37 +00001303 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001304}
1305
njn4aca2d22002-10-04 10:29:38 +00001306Int VG_(unlink) ( Char* file_name )
1307{
1308 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001309 res = VG_(do_syscall)(__NR_unlink, (UWord)file_name);
njn41557122002-10-14 09:25:37 +00001310 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001311}
1312
njn13f02932003-04-30 20:23:58 +00001313/* Nb: we do not allow the Linux extension which malloc()s memory for the
1314 buffer if buf==NULL, because we don't want Linux calling malloc() */
nethercote928a5f72004-11-03 18:10:37 +00001315Char* VG_(getcwd) ( Char* buf, SizeT size )
njn13f02932003-04-30 20:23:58 +00001316{
1317 Int res;
1318 vg_assert(buf != NULL);
nethercotecf51cc42004-11-04 17:02:42 +00001319 res = VG_(do_syscall)(__NR_getcwd, (UWord)buf, size);
njn13f02932003-04-30 20:23:58 +00001320 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1321}
1322
njn99ccf082003-09-30 13:51:23 +00001323/* Alternative version that does allocate the memory. Easier to use. */
1324Bool VG_(getcwd_alloc) ( Char** out )
1325{
nethercote928a5f72004-11-03 18:10:37 +00001326 SizeT size = 4;
njn99ccf082003-09-30 13:51:23 +00001327
1328 *out = NULL;
1329 while (True) {
1330 *out = VG_(malloc)(size);
1331 if (NULL == VG_(getcwd)(*out, size)) {
1332 VG_(free)(*out);
1333 if (size > 65535)
1334 return False;
1335 size *= 2;
1336 } else {
1337 return True;
1338 }
1339 }
1340}
1341
njn13f02932003-04-30 20:23:58 +00001342
1343/* ---------------------------------------------------------------------
1344 Misc functions looking for a proper home.
1345 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001346
nethercoteff9721d2004-01-26 17:10:01 +00001347/* clone the environment */
nethercote85cdd342004-08-01 22:36:40 +00001348static Char **env_clone ( Char **oldenv )
nethercoteff9721d2004-01-26 17:10:01 +00001349{
1350 Char **oldenvp;
1351 Char **newenvp;
1352 Char **newenv;
1353 Int envlen;
1354
1355 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
1356
1357 envlen = oldenvp - oldenv + 1;
1358
1359 newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1360
1361 oldenvp = oldenv;
1362 newenvp = newenv;
1363
1364 while (oldenvp && *oldenvp) {
1365 *newenvp++ = *oldenvp++;
1366 }
1367
1368 *newenvp = *oldenvp;
1369
1370 return newenv;
1371}
1372
fitzhardinge98abfc72003-12-16 02:05:15 +00001373void VG_(env_unsetenv) ( Char **env, const Char *varname )
1374{
1375 Char **from;
1376 Char **to = NULL;
1377 Int len = VG_(strlen)(varname);
1378
1379 for(from = to = env; from && *from; from++) {
1380 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
1381 *to = *from;
1382 to++;
1383 }
1384 }
1385 *to = *from;
1386}
1387
1388/* set the environment; returns the old env if a new one was allocated */
1389Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
1390{
1391 Char **env = (*envp);
1392 Char **cpp;
1393 Int len = VG_(strlen)(varname);
1394 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, len + VG_(strlen)(val) + 2);
1395 Char **oldenv = NULL;
1396
1397 VG_(sprintf)(valstr, "%s=%s", varname, val);
1398
1399 for(cpp = env; cpp && *cpp; cpp++) {
1400 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
1401 *cpp = valstr;
1402 return oldenv;
1403 }
1404 }
1405
1406 if (env == NULL) {
1407 env = VG_(arena_malloc)(VG_AR_CORE, sizeof(Char **) * 2);
1408 env[0] = valstr;
1409 env[1] = NULL;
1410
1411 *envp = env;
1412
1413 } else {
1414 Int envlen = (cpp-env) + 2;
1415 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1416
1417 for(cpp = newenv; *env; )
1418 *cpp++ = *env++;
1419 *cpp++ = valstr;
1420 *cpp++ = NULL;
1421
1422 oldenv = *envp;
1423
1424 *envp = newenv;
1425 }
1426
1427 return oldenv;
1428}
1429
nethercote85cdd342004-08-01 22:36:40 +00001430/* We do getenv without libc's help by snooping around in
1431 VG_(client_envp) as determined at startup time. */
1432Char *VG_(getenv)(Char *varname)
sewardjde4a1d02002-03-22 01:27:54 +00001433{
1434 Int i, n;
1435 n = VG_(strlen)(varname);
nethercote85cdd342004-08-01 22:36:40 +00001436 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1437 Char* s = VG_(client_envp)[i];
sewardjde4a1d02002-03-22 01:27:54 +00001438 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1439 return & s[n+1];
1440 }
1441 }
1442 return NULL;
1443}
1444
rjwalshf5f536f2003-11-17 17:45:00 +00001445/* Support for getrlimit. */
1446Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
1447{
1448 Int res;
1449 /* res = getrlimit( resource, rlim ); */
nethercotecf51cc42004-11-04 17:02:42 +00001450 res = VG_(do_syscall)(__NR_getrlimit, resource, (UWord)rlim);
rjwalshf5f536f2003-11-17 17:45:00 +00001451 if(VG_(is_kerror)(res)) res = -1;
1452 return res;
1453}
1454
1455
fitzhardingef0046f22003-12-18 02:39:22 +00001456/* Support for setrlimit. */
1457Int VG_(setrlimit) (Int resource, struct vki_rlimit *rlim)
1458{
1459 Int res;
1460 /* res = setrlimit( resource, rlim ); */
nethercotecf51cc42004-11-04 17:02:42 +00001461 res = VG_(do_syscall)(__NR_setrlimit, resource, (UWord)rlim);
fitzhardingef0046f22003-12-18 02:39:22 +00001462 if(VG_(is_kerror)(res)) res = -1;
1463 return res;
1464}
1465
1466
rjwalshf5f536f2003-11-17 17:45:00 +00001467/* Support for getdents. */
1468Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
1469{
1470 Int res;
1471 /* res = getdents( fd, dirp, count ); */
nethercotecf51cc42004-11-04 17:02:42 +00001472 res = VG_(do_syscall)(__NR_getdents, fd, (UWord)dirp, count);
rjwalshf5f536f2003-11-17 17:45:00 +00001473 if (VG_(is_kerror)(res)) res = -1;
1474 return res;
1475}
1476
1477/* Support for a readlink. */
1478Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
1479{
1480 Int res;
1481 /* res = readlink( path, buf, bufsiz ); */
nethercotecf51cc42004-11-04 17:02:42 +00001482 res = VG_(do_syscall)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
rjwalshf5f536f2003-11-17 17:45:00 +00001483 if (VG_(is_kerror)(res)) res = -1;
1484 return res;
1485}
1486
sewardjde4a1d02002-03-22 01:27:54 +00001487/* You'd be amazed how many places need to know the current pid. */
1488Int VG_(getpid) ( void )
1489{
1490 Int res;
1491 /* res = getpid(); */
jsgf855d93d2003-10-13 22:26:55 +00001492 res = VG_(do_syscall)(__NR_getpid);
1493 return res;
1494}
1495
1496Int VG_(getpgrp) ( void )
1497{
1498 Int res;
1499 /* res = getpgid(); */
1500 res = VG_(do_syscall)(__NR_getpgrp);
sewardjde4a1d02002-03-22 01:27:54 +00001501 return res;
1502}
1503
sewardj4cf05692002-10-27 20:28:29 +00001504Int VG_(getppid) ( void )
1505{
1506 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001507 res = VG_(do_syscall)(__NR_getppid);
sewardj4cf05692002-10-27 20:28:29 +00001508 return res;
1509}
1510
jsgf855d93d2003-10-13 22:26:55 +00001511Int VG_(setpgid) ( Int pid, Int pgrp )
1512{
1513 return VG_(do_syscall)(__NR_setpgid, pid, pgrp);
1514}
sewardj4cf05692002-10-27 20:28:29 +00001515
nethercote60a96c52004-08-03 13:08:31 +00001516/* Walk through a colon-separated environment variable, and remove the
1517 entries which match remove_pattern. It slides everything down over
1518 the removed entries, and pads the remaining space with '\0'. It
1519 modifies the entries in place (in the client address space), but it
1520 shouldn't matter too much, since we only do this just before an
1521 execve().
1522
1523 This is also careful to mop up any excess ':'s, since empty strings
1524 delimited by ':' are considered to be '.' in a path.
1525*/
1526static void mash_colon_env(Char *varp, const Char *remove_pattern)
1527{
1528 Char *const start = varp;
1529 Char *entry_start = varp;
1530 Char *output = varp;
1531
1532 if (varp == NULL)
1533 return;
1534
1535 while(*varp) {
1536 if (*varp == ':') {
1537 Char prev;
1538 Bool match;
1539
1540 /* This is a bit subtle: we want to match against the entry
1541 we just copied, because it may have overlapped with
1542 itself, junking the original. */
1543
1544 prev = *output;
1545 *output = '\0';
1546
1547 match = VG_(string_match)(remove_pattern, entry_start);
1548
1549 *output = prev;
1550
1551 if (match) {
1552 output = entry_start;
1553 varp++; /* skip ':' after removed entry */
1554 } else
1555 entry_start = output+1; /* entry starts after ':' */
1556 }
1557
1558 *output++ = *varp++;
1559 }
1560
1561 /* match against the last entry */
1562 if (VG_(string_match)(remove_pattern, entry_start)) {
1563 output = entry_start;
1564 if (output > start) {
1565 /* remove trailing ':' */
1566 output--;
1567 vg_assert(*output == ':');
1568 }
1569 }
1570
1571 /* pad out the left-overs with '\0' */
1572 while(output < varp)
1573 *output++ = '\0';
1574}
1575
1576
1577// Removes all the Valgrind-added stuff from the passed environment. Used
1578// when starting child processes, so they don't see that added stuff.
1579void VG_(env_remove_valgrind_env_stuff)(Char** envp)
1580{
1581 Int i;
1582 Char* ld_preload_str = NULL;
1583 Char* ld_library_path_str = NULL;
1584 Char* buf;
1585
1586 // Find LD_* variables
1587 for (i = 0; envp[i] != NULL; i++) {
1588 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
1589 ld_preload_str = &envp[i][11];
1590 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
1591 ld_library_path_str = &envp[i][16];
1592 }
1593
1594 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
1595
1596 // Remove Valgrind-specific entries from LD_*.
1597 VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
1598 mash_colon_env(ld_preload_str, buf);
1599 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
1600 mash_colon_env(ld_preload_str, buf);
1601 VG_(sprintf)(buf, "%s*", VG_(libdir));
1602 mash_colon_env(ld_library_path_str, buf);
1603
1604 // Remove VALGRIND_CLO variable.
1605 VG_(env_unsetenv)(envp, VALGRINDCLO);
1606
1607 // XXX if variable becomes empty, remove it completely?
1608
1609 VG_(arena_free)(VG_AR_CORE, buf);
1610}
1611
sewardje6a25242002-04-21 22:03:07 +00001612/* Return -1 if error, else 0. NOTE does not indicate return code of
1613 child! */
1614Int VG_(system) ( Char* cmd )
1615{
1616 Int pid, res;
sewardje6a25242002-04-21 22:03:07 +00001617 if (cmd == NULL)
1618 return 1;
jsgf855d93d2003-10-13 22:26:55 +00001619 pid = VG_(do_syscall)(__NR_fork);
sewardje6a25242002-04-21 22:03:07 +00001620 if (VG_(is_kerror)(pid))
1621 return -1;
1622 if (pid == 0) {
1623 /* child */
nethercoteff9721d2004-01-26 17:10:01 +00001624 static Char** envp = NULL;
sewardje6a25242002-04-21 22:03:07 +00001625 Char* argv[4];
nethercoteff9721d2004-01-26 17:10:01 +00001626
fitzhardingeb50068f2004-02-24 23:42:55 +00001627 /* restore the DATA rlimit for the child */
1628 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1629
nethercote60a96c52004-08-03 13:08:31 +00001630 envp = env_clone(VG_(client_envp));
1631 VG_(env_remove_valgrind_env_stuff)( envp );
nethercoteff9721d2004-01-26 17:10:01 +00001632
sewardje6a25242002-04-21 22:03:07 +00001633 argv[0] = "/bin/sh";
1634 argv[1] = "-c";
1635 argv[2] = cmd;
1636 argv[3] = 0;
nethercoteff9721d2004-01-26 17:10:01 +00001637
jsgf855d93d2003-10-13 22:26:55 +00001638 (void)VG_(do_syscall)(__NR_execve,
nethercote50397c22004-11-04 18:03:06 +00001639 (UWord)"/bin/sh", (UWord)argv, (UWord)envp);
nethercoteff9721d2004-01-26 17:10:01 +00001640
sewardje6a25242002-04-21 22:03:07 +00001641 /* If we're still alive here, execve failed. */
fitzhardingeabab8392004-03-02 21:38:51 +00001642 VG_(exit)(1);
sewardje6a25242002-04-21 22:03:07 +00001643 } else {
1644 /* parent */
fitzhardingeabab8392004-03-02 21:38:51 +00001645 res = VG_(waitpid)(pid, NULL, 0);
sewardje6a25242002-04-21 22:03:07 +00001646 if (VG_(is_kerror)(res)) {
1647 return -1;
1648 } else {
fitzhardingeabab8392004-03-02 21:38:51 +00001649 return 0;
sewardje6a25242002-04-21 22:03:07 +00001650 }
1651 }
1652}
1653
1654
sewardjde4a1d02002-03-22 01:27:54 +00001655/* ---------------------------------------------------------------------
fitzhardinge66871692004-01-25 03:32:58 +00001656 Support for a millisecond-granularity timer.
sewardj5f07b662002-04-23 16:52:51 +00001657 ------------------------------------------------------------------ */
1658
sewardj5f07b662002-04-23 16:52:51 +00001659UInt VG_(read_millisecond_timer) ( void )
1660{
fitzhardinge426f9e62004-01-25 03:44:18 +00001661 static ULong base = 0;
fitzhardinge66871692004-01-25 03:32:58 +00001662 struct vki_timeval tv_now;
1663 ULong now;
sewardj5f07b662002-04-23 16:52:51 +00001664 Int res;
sewardj5f07b662002-04-23 16:52:51 +00001665
nethercotefbd6ffd2004-11-04 17:10:24 +00001666 res = VG_(do_syscall)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001667
fitzhardinge66871692004-01-25 03:32:58 +00001668 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1669
1670 if (base == 0)
1671 base = now;
sewardj5f07b662002-04-23 16:52:51 +00001672
fitzhardinge66871692004-01-25 03:32:58 +00001673 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +00001674}
1675
1676
sewardj5f07b662002-04-23 16:52:51 +00001677/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001678 Primitive support for bagging memory via mmap.
1679 ------------------------------------------------------------------ */
1680
nethercote8b5f40c2004-11-02 13:29:50 +00001681void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001682{
nethercote8b5f40c2004-11-02 13:29:50 +00001683 static SizeT tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001684 void* p;
nethercotec314eba2004-07-15 12:59:41 +00001685 p = VG_(mmap)(0, nBytes,
1686 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1687 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001688
sewardjde4a1d02002-03-22 01:27:54 +00001689 if (p != ((void*)(-1))) {
nethercotefb583e22004-09-07 23:15:37 +00001690 vg_assert((void*)VG_(valgrind_base) <= p && p <= (void*)VG_(valgrind_last));
nethercote50397c22004-11-04 18:03:06 +00001691 tot_alloc += nBytes;
sewardjde4a1d02002-03-22 01:27:54 +00001692 if (0)
sewardje9047952002-06-05 20:28:33 +00001693 VG_(printf)(
nethercote8b5f40c2004-11-02 13:29:50 +00001694 "get_memory_from_mmap: %llu tot, %llu req = %p .. %p, caller %s\n",
1695 (ULong)tot_alloc, (ULong)nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001696 return p;
1697 }
sewardj7c2020b2002-09-30 22:56:03 +00001698
njn25e49d8e72002-09-23 09:36:25 +00001699 VG_(printf)("\n");
nethercote8b5f40c2004-11-02 13:29:50 +00001700 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %llu bytes failed.\n",
1701 who, (ULong)nBytes);
1702 VG_(printf)("VG_(get_memory_from_mmap): %llu bytes already allocated.\n",
1703 (ULong)tot_alloc);
njn25e49d8e72002-09-23 09:36:25 +00001704 VG_(printf)("\n");
nethercotee757d6e2004-07-10 16:17:52 +00001705 VG_(printf)("Sorry. You could try using a tool that uses less memory;\n");
1706 VG_(printf)("eg. addrcheck instead of memcheck.\n");
njn25e49d8e72002-09-23 09:36:25 +00001707 VG_(printf)("\n");
1708 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001709}
1710
njn25e49d8e72002-09-23 09:36:25 +00001711/* ---------------------------------------------------------------------
1712 Generally useful...
1713 ------------------------------------------------------------------ */
1714
1715Int VG_(log2) ( Int x )
1716{
1717 Int i;
1718 /* Any more than 32 and we overflow anyway... */
1719 for (i = 0; i < 32; i++) {
1720 if (1 << i == x) return i;
1721 }
1722 return -1;
1723}
1724
1725
njnd3b0c5f2003-09-30 14:43:54 +00001726// Generic shell sort. Like stdlib.h's qsort().
nethercote928a5f72004-11-03 18:10:37 +00001727void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
njnd3b0c5f2003-09-30 14:43:54 +00001728 Int (*compar)(void*, void*) )
1729{
1730 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1731 9841, 29524, 88573, 265720,
1732 797161, 2391484 };
1733 Int lo = 0;
1734 Int hi = nmemb-1;
1735 Int i, j, h, bigN, hp;
1736
1737 bigN = hi - lo + 1; if (bigN < 2) return;
1738 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1739 vg_assert(0 <= hp && hp < 14);
1740
1741 #define SORT \
1742 for ( ; hp >= 0; hp--) { \
1743 h = incs[hp]; \
njn92c54362003-10-15 14:00:35 +00001744 for (i = lo + h; i <= hi; i++) { \
njnd3b0c5f2003-09-30 14:43:54 +00001745 ASSIGN(v,0, a,i); \
1746 j = i; \
njn92c54362003-10-15 14:00:35 +00001747 while (COMPAR(a,(j-h), v,0) > 0) { \
njnd3b0c5f2003-09-30 14:43:54 +00001748 ASSIGN(a,j, a,(j-h)); \
1749 j = j - h; \
1750 if (j <= (lo + h - 1)) break; \
1751 } \
1752 ASSIGN(a,j, v,0); \
njnd3b0c5f2003-09-30 14:43:54 +00001753 } \
1754 }
1755
1756 // Specialised cases
nethercote928a5f72004-11-03 18:10:37 +00001757 if (sizeof(ULong) == size) {
njnd3b0c5f2003-09-30 14:43:54 +00001758
1759 #define ASSIGN(dst, dsti, src, srci) \
1760 (dst)[(dsti)] = (src)[(srci)];
1761
1762 #define COMPAR(dst, dsti, src, srci) \
1763 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1764
nethercote928a5f72004-11-03 18:10:37 +00001765 ULong* a = (ULong*)base;
1766 ULong v[1];
1767
1768 SORT;
1769
1770 } else if (sizeof(UInt) == size) {
1771
njnd3b0c5f2003-09-30 14:43:54 +00001772 UInt* a = (UInt*)base;
1773 UInt v[1];
1774
1775 SORT;
1776
1777 } else if (sizeof(UShort) == size) {
1778 UShort* a = (UShort*)base;
1779 UShort v[1];
1780
1781 SORT;
1782
1783 } else if (sizeof(UChar) == size) {
1784 UChar* a = (UChar*)base;
1785 UChar v[1];
1786
1787 SORT;
1788
1789 #undef ASSIGN
1790 #undef COMPAR
1791
1792 // General case
1793 } else {
njn92c54362003-10-15 14:00:35 +00001794 char* a = base;
1795 char v[size]; // will be at least 'size' bytes
njnd3b0c5f2003-09-30 14:43:54 +00001796
1797 #define ASSIGN(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001798 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
njnd3b0c5f2003-09-30 14:43:54 +00001799
1800 #define COMPAR(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001801 compar( &dst[size*(dsti)], &src[size*(srci)] )
njnd3b0c5f2003-09-30 14:43:54 +00001802
1803 SORT;
1804
1805 #undef ASSIGN
1806 #undef COMPAR
1807 }
1808 #undef SORT
1809}
1810
sewardj73cf3bc2002-11-03 03:20:15 +00001811/* ---------------------------------------------------------------------
1812 Gruesome hackery for connecting to a logging server over the network.
1813 This is all very Linux-kernel specific.
1814 ------------------------------------------------------------------ */
1815
sewardj73cf3bc2002-11-03 03:20:15 +00001816static
1817Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1818
1819static
1820Int my_socket ( Int domain, Int type, Int protocol );
1821
1822static
1823Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1824 Int addrlen );
1825
1826static
1827UInt my_htonl ( UInt x )
1828{
1829 return
1830 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1831 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1832}
1833
1834static
1835UShort my_htons ( UShort x )
1836{
1837 return
1838 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1839}
1840
1841
1842/* The main function.
1843
1844 Supplied string contains either an ip address "192.168.0.1" or
1845 an ip address and port pair, "192.168.0.1:1500". Parse these,
1846 and return:
1847 -1 if there is a parse error
1848 -2 if no parse error, but specified host:port cannot be opened
1849 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001850 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001851*/
1852Int VG_(connect_via_socket)( UChar* str )
1853{
1854 Int sd, res;
1855 struct vki_sockaddr_in servAddr;
1856 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001857 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001858 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1859 if (!ok)
1860 return -1;
1861
1862 if (0)
1863 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1864 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1865 (ip >> 8) & 0xFF, ip & 0xFF,
1866 (UInt)port );
1867
nethercote73b526f2004-10-31 18:48:21 +00001868 servAddr.sin_family = VKI_AF_INET;
sewardj73cf3bc2002-11-03 03:20:15 +00001869 servAddr.sin_addr.s_addr = my_htonl(ip);
1870 servAddr.sin_port = my_htons(port);
1871
1872 /* create socket */
nethercote73b526f2004-10-31 18:48:21 +00001873 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
sewardj73cf3bc2002-11-03 03:20:15 +00001874 if (sd < 0) {
1875 /* this shouldn't happen ... nevertheless */
1876 return -2;
1877 }
1878
1879 /* connect to server */
1880 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1881 sizeof(servAddr));
1882 if (res < 0) {
1883 /* connection failed */
1884 return -2;
1885 }
1886
1887 return sd;
1888}
1889
1890
1891/* Let d = one or more digits. Accept either:
1892 d.d.d.d or d.d.d.d:d
1893*/
1894Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1895{
1896# define GET_CH ((*str) ? (*str++) : 0)
1897 UInt ipa, i, j, c, any;
1898 ipa = 0;
1899 for (i = 0; i < 4; i++) {
1900 j = 0;
1901 any = 0;
1902 while (1) {
1903 c = GET_CH;
1904 if (c < '0' || c > '9') break;
1905 j = 10 * j + (int)(c - '0');
1906 any = 1;
1907 }
1908 if (any == 0 || j > 255) goto syntaxerr;
1909 ipa = (ipa << 8) + j;
1910 if (i <= 2 && c != '.') goto syntaxerr;
1911 }
1912 if (c == 0 || c == ':')
1913 *ip_addr = ipa;
1914 if (c == 0) goto ok;
1915 if (c != ':') goto syntaxerr;
1916 j = 0;
1917 any = 0;
1918 while (1) {
1919 c = GET_CH;
1920 if (c < '0' || c > '9') break;
1921 j = j * 10 + (int)(c - '0');
1922 any = 1;
1923 if (j > 65535) goto syntaxerr;
1924 }
1925 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001926 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001927 *port = (UShort)j;
1928 ok:
1929 return 1;
1930 syntaxerr:
1931 return 0;
1932# undef GET_CH
1933}
1934
1935
1936static
1937Int my_socket ( Int domain, Int type, Int protocol )
1938{
1939 Int res;
nethercotebf779682004-11-04 17:24:57 +00001940 UWord args[3];
sewardj73cf3bc2002-11-03 03:20:15 +00001941 args[0] = domain;
1942 args[1] = type;
1943 args[2] = protocol;
nethercotecf51cc42004-11-04 17:02:42 +00001944 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001945 if (VG_(is_kerror)(res))
1946 res = -1;
1947 return res;
1948}
1949
1950static
1951Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1952 Int addrlen )
1953{
1954 Int res;
nethercotebf779682004-11-04 17:24:57 +00001955 UWord args[3];
sewardj73cf3bc2002-11-03 03:20:15 +00001956 args[0] = sockfd;
nethercotebf779682004-11-04 17:24:57 +00001957 args[1] = (UWord)serv_addr;
sewardj73cf3bc2002-11-03 03:20:15 +00001958 args[2] = addrlen;
nethercotecf51cc42004-11-04 17:02:42 +00001959 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001960 if (VG_(is_kerror)(res))
1961 res = -1;
1962 return res;
1963}
1964
1965Int VG_(write_socket)( Int sd, void *msg, Int count )
1966{
1967 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001968
1969 /* Requests not to send SIGPIPE on errors on stream oriented
1970 sockets when the other end breaks the connection. The EPIPE
1971 error is still returned. */
nethercote73b526f2004-10-31 18:48:21 +00001972 Int flags = VKI_MSG_NOSIGNAL;
sewardj570f8902002-11-03 11:44:36 +00001973
sewardj73cf3bc2002-11-03 03:20:15 +00001974 Int res;
nethercotebf779682004-11-04 17:24:57 +00001975 UWord args[4];
sewardj73cf3bc2002-11-03 03:20:15 +00001976 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00001977 args[1] = (UWord)msg;
sewardj73cf3bc2002-11-03 03:20:15 +00001978 args[2] = count;
1979 args[3] = flags;
nethercotecf51cc42004-11-04 17:02:42 +00001980 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001981 if (VG_(is_kerror)(res))
1982 res = -1;
1983 return res;
1984}
1985
rjwalshf5f536f2003-11-17 17:45:00 +00001986Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1987{
1988 Int res;
nethercotebf779682004-11-04 17:24:57 +00001989 UWord args[3];
rjwalshf5f536f2003-11-17 17:45:00 +00001990 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00001991 args[1] = (UWord)name;
1992 args[2] = (UWord)namelen;
nethercotecf51cc42004-11-04 17:02:42 +00001993 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
rjwalshf5f536f2003-11-17 17:45:00 +00001994 if(VG_(is_kerror)(res))
1995 res = -1;
1996 return res;
1997}
1998
1999Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
2000{
2001 Int res;
nethercotebf779682004-11-04 17:24:57 +00002002 UWord args[3];
rjwalshf5f536f2003-11-17 17:45:00 +00002003 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00002004 args[1] = (UWord)name;
2005 args[2] = (UWord)namelen;
nethercotecf51cc42004-11-04 17:02:42 +00002006 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
rjwalshf5f536f2003-11-17 17:45:00 +00002007 if(VG_(is_kerror)(res))
2008 res = -1;
2009 return res;
2010}
2011
2012Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
2013 Int *optlen)
2014{
2015 Int res;
nethercotebf779682004-11-04 17:24:57 +00002016 UWord args[5];
rjwalshf5f536f2003-11-17 17:45:00 +00002017 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00002018 args[1] = level;
2019 args[2] = optname;
2020 args[3] = (UWord)optval;
2021 args[4] = (UWord)optlen;
nethercotecf51cc42004-11-04 17:02:42 +00002022 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
rjwalshf5f536f2003-11-17 17:45:00 +00002023 if(VG_(is_kerror)(res))
2024 res = -1;
2025 return res;
2026}
2027
sewardjde4a1d02002-03-22 01:27:54 +00002028
2029/*--------------------------------------------------------------------*/
2030/*--- end vg_mylibc.c ---*/
2031/*--------------------------------------------------------------------*/