blob: 11ee81497ac7c7b7f189564d4f3b500dceac0980 [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
njnc6168192004-11-29 13:54:10 +0000198Int VG_(tkill)( ThreadId 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{
njnc6168192004-11-29 13:54:10 +0000219// Nb: AMD64/Linux doesn't have __NR_sigpending; it only provides
220// __NR_rt_sigpending. This function will have to be abstracted in some
221// way to account for this. In the meantime, the easy option is to forget
222// about it for AMD64 until it's needed.
223#ifdef __amd64__
224 I_die_here;
225#else
nethercotecf51cc42004-11-04 17:02:42 +0000226 Int res = VG_(do_syscall)(__NR_sigpending, (UWord)set);
sewardjefbfcdf2002-06-19 17:35:45 +0000227 return VG_(is_kerror)(res) ? -1 : 0;
njnc6168192004-11-29 13:54:10 +0000228#endif
sewardjefbfcdf2002-06-19 17:35:45 +0000229}
230
jsgf855d93d2003-10-13 22:26:55 +0000231Int VG_(waitpid)(Int pid, Int *status, Int options)
232{
233 Int ret = VG_(do_syscall)(__NR_wait4, pid, status, options, NULL);
234
235 return VG_(is_kerror)(ret) ? -1 : ret;
236}
237
238Int VG_(gettid)(void)
239{
240 Int ret;
241
242 ret = VG_(do_syscall)(__NR_gettid);
243
thughes8ef6d962004-10-16 10:46:01 +0000244 if (ret == -VKI_ENOSYS) {
245 Char pid[16];
246
247 /*
248 * The gettid system call does not exist. The obvious assumption
249 * to make at this point would be that we are running on an older
250 * system where the getpid system call actually returns the ID of
251 * the current thread.
252 *
253 * Unfortunately it seems that there are some systems with a kernel
254 * where getpid has been changed to return the ID of the thread group
255 * leader but where the gettid system call has not yet been added.
256 *
257 * So instead of calling getpid here we use readlink to see where
258 * the /proc/self link is pointing...
259 */
260 if ((ret = VG_(do_syscall)(__NR_readlink, "/proc/self", pid, sizeof(pid))) >= 0) {
261 pid[ret] = '\0';
262 ret = VG_(atoll)(pid);
263 }
264 }
jsgf855d93d2003-10-13 22:26:55 +0000265
266 return ret;
267}
268
269
sewardjefbfcdf2002-06-19 17:35:45 +0000270
sewardjde4a1d02002-03-22 01:27:54 +0000271/* ---------------------------------------------------------------------
sewardj2e93c502002-04-12 11:12:52 +0000272 mmap/munmap, exit, fcntl
sewardjde4a1d02002-03-22 01:27:54 +0000273 ------------------------------------------------------------------ */
274
nethercotecf51cc42004-11-04 17:02:42 +0000275static Int munmap_inner(void *start, SizeT length)
fitzhardingeb50068f2004-02-24 23:42:55 +0000276{
nethercotecf51cc42004-11-04 17:02:42 +0000277 return VG_(do_syscall)(__NR_munmap, (UWord)start, length );
fitzhardingeb50068f2004-02-24 23:42:55 +0000278}
279
nethercote5b9fafd2004-11-04 18:39:22 +0000280static Addr mmap_inner(void *start, SizeT length, UInt prot, UInt flags,
281 UInt fd, OffT offset)
fitzhardingeb50068f2004-02-24 23:42:55 +0000282{
nethercote6456ab12004-10-18 14:47:48 +0000283 Int ret;
284
285 PLATFORM_DO_MMAP(ret, start, length, prot,
286 flags & ~(VKI_MAP_NOSYMS|VKI_MAP_CLIENT),
287 fd, offset);
288 return ret;
fitzhardingeb50068f2004-02-24 23:42:55 +0000289}
290
sewardjde4a1d02002-03-22 01:27:54 +0000291/* Returns -1 on failure. */
nethercote8b5f40c2004-11-02 13:29:50 +0000292void* VG_(mmap)( void* start, SizeT length,
nethercote5b9fafd2004-11-04 18:39:22 +0000293 UInt prot, UInt flags, UInt sf_flags, UInt fd, OffT offset)
sewardjde4a1d02002-03-22 01:27:54 +0000294{
fitzhardinge98abfc72003-12-16 02:05:15 +0000295 Addr res;
fitzhardinge98abfc72003-12-16 02:05:15 +0000296
297 if (!(flags & VKI_MAP_FIXED)) {
298 start = (void *)VG_(find_map_space)((Addr)start, length, !!(flags & VKI_MAP_CLIENT));
fitzhardinge98abfc72003-12-16 02:05:15 +0000299
300 flags |= VKI_MAP_FIXED;
301 }
nethercoteb4250ae2004-07-10 16:50:09 +0000302 if (start == 0)
303 return (void *)-1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000304
fitzhardingeb50068f2004-02-24 23:42:55 +0000305 res = mmap_inner(start, length, prot, flags, fd, offset);
fitzhardinge98abfc72003-12-16 02:05:15 +0000306
nethercoteb4250ae2004-07-10 16:50:09 +0000307 // Check it ended up in the right place.
fitzhardinge98abfc72003-12-16 02:05:15 +0000308 if (!VG_(is_kerror)(res)) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000309 if (flags & VKI_MAP_CLIENT) {
nethercote00600502004-09-11 23:27:09 +0000310 vg_assert(VG_(client_base) <= res && res+length <= VG_(client_end));
fitzhardinge98abfc72003-12-16 02:05:15 +0000311 } else {
nethercotefb583e22004-09-07 23:15:37 +0000312 vg_assert(VG_(valgrind_base) <= res && res+length-1 <= VG_(valgrind_last));
fitzhardinge98abfc72003-12-16 02:05:15 +0000313 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000314
nethercoteb4250ae2004-07-10 16:50:09 +0000315 sf_flags |= SF_MMAP;
316 if ( flags & VKI_MAP_FIXED) sf_flags |= SF_FIXED;
317 if ( flags & VKI_MAP_SHARED) sf_flags |= SF_SHARED;
318 if (!(flags & VKI_MAP_ANONYMOUS)) sf_flags |= SF_FILE;
319 if (!(flags & VKI_MAP_CLIENT)) sf_flags |= SF_VALGRIND;
320 if ( flags & VKI_MAP_NOSYMS) sf_flags |= SF_NOSYMS;
321
322 VG_(map_fd_segment)(res, length, prot, sf_flags, fd, offset, NULL);
323 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000324
sewardjde4a1d02002-03-22 01:27:54 +0000325 return VG_(is_kerror)(res) ? ((void*)(-1)) : (void*)res;
326}
327
328/* Returns -1 on failure. */
nethercote8b5f40c2004-11-02 13:29:50 +0000329Int VG_(munmap)( void* start, SizeT length )
sewardjde4a1d02002-03-22 01:27:54 +0000330{
fitzhardingeb50068f2004-02-24 23:42:55 +0000331 Int res = munmap_inner(start, length);
fitzhardinge920d04e2003-12-20 18:19:50 +0000332 if (!VG_(is_kerror)(res))
fitzhardinge98abfc72003-12-16 02:05:15 +0000333 VG_(unmap_range)((Addr)start, length);
334 return VG_(is_kerror)(res) ? -1 : 0;
335}
336
nethercote8b5f40c2004-11-02 13:29:50 +0000337Int VG_(mprotect)( void *start, SizeT length, UInt prot )
fitzhardinge98abfc72003-12-16 02:05:15 +0000338{
nethercote8b5f40c2004-11-02 13:29:50 +0000339 Int res = VG_(do_syscall)(__NR_mprotect, (UWord)start, length, prot );
fitzhardinge98abfc72003-12-16 02:05:15 +0000340 if (!VG_(is_kerror)(res))
341 VG_(mprotect_range)((Addr)start, length, prot);
sewardjde4a1d02002-03-22 01:27:54 +0000342 return VG_(is_kerror)(res) ? -1 : 0;
343}
344
345void VG_(exit)( Int status )
346{
nethercotecf51cc42004-11-04 17:02:42 +0000347 (void)VG_(do_syscall)(__NR_exit_group, status );
348 (void)VG_(do_syscall)(__NR_exit, status );
sewardjde4a1d02002-03-22 01:27:54 +0000349 /* Why are we still alive here? */
350 /*NOTREACHED*/
jsgf855d93d2003-10-13 22:26:55 +0000351 *(volatile Int *)0 = 'x';
sewardjde4a1d02002-03-22 01:27:54 +0000352 vg_assert(2+2 == 5);
353}
354
sewardj2e93c502002-04-12 11:12:52 +0000355/* Returns -1 on error. */
356Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
357{
jsgf855d93d2003-10-13 22:26:55 +0000358 Int res = VG_(do_syscall)(__NR_fcntl, fd, cmd, arg);
sewardj2e93c502002-04-12 11:12:52 +0000359 return VG_(is_kerror)(res) ? -1 : res;
360}
361
jsgf855d93d2003-10-13 22:26:55 +0000362Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
363{
364 Int res = VG_(do_syscall)(__NR_poll, ufds, nfds, timeout);
365
366 return res;
367}
368
sewardj2e93c502002-04-12 11:12:52 +0000369
sewardjde4a1d02002-03-22 01:27:54 +0000370/* ---------------------------------------------------------------------
371 printf implementation. The key function, vg_vprintf(), emits chars
372 into a caller-supplied function. Distantly derived from:
373
374 vprintf replacement for Checker.
375 Copyright 1993, 1994, 1995 Tristan Gingold
376 Written September 1993 Tristan Gingold
377 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
378
379 (Checker itself was GPL'd.)
380 ------------------------------------------------------------------ */
381
382
383/* Some flags. */
384#define VG_MSG_SIGNED 1 /* The value is signed. */
385#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
386#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
sewardj78e3cd92002-10-22 04:45:48 +0000387#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
njn607adfc2003-09-30 14:15:44 +0000388#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
sewardjde4a1d02002-03-22 01:27:54 +0000389
390/* Copy a string into the buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000391static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000392myvprintf_str ( void(*send)(Char), Int flags, Int width, Char* str,
393 Bool capitalise )
394{
395# define MAYBE_TOUPPER(ch) (capitalise ? VG_(toupper)(ch) : (ch))
sewardj78e3cd92002-10-22 04:45:48 +0000396 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000397 Int i, extra;
398 Int len = VG_(strlen)(str);
399
400 if (width == 0) {
sewardj78e3cd92002-10-22 04:45:48 +0000401 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000402 for (i = 0; i < len; i++)
403 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000404 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000405 }
406
407 if (len > width) {
sewardj78e3cd92002-10-22 04:45:48 +0000408 ret += width;
sewardjde4a1d02002-03-22 01:27:54 +0000409 for (i = 0; i < width; i++)
410 send(MAYBE_TOUPPER(str[i]));
sewardj78e3cd92002-10-22 04:45:48 +0000411 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000412 }
413
414 extra = width - len;
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 }
sewardj78e3cd92002-10-22 04:45:48 +0000420 ret += len;
sewardjde4a1d02002-03-22 01:27:54 +0000421 for (i = 0; i < len; i++)
422 send(MAYBE_TOUPPER(str[i]));
423 if (!(flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000424 ret += extra;
sewardjde4a1d02002-03-22 01:27:54 +0000425 for (i = 0; i < extra; i++)
426 send(' ');
427 }
428
429# undef MAYBE_TOUPPER
sewardj78e3cd92002-10-22 04:45:48 +0000430
431 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000432}
433
434/* Write P into the buffer according to these args:
435 * If SIGN is true, p is a signed.
436 * BASE is the base.
437 * If WITH_ZERO is true, '0' must be added.
438 * WIDTH is the width of the field.
439 */
sewardj78e3cd92002-10-22 04:45:48 +0000440static UInt
sewardjde4a1d02002-03-22 01:27:54 +0000441myvprintf_int64 ( void(*send)(Char), Int flags, Int base, Int width, ULong p)
442{
443 Char buf[40];
444 Int ind = 0;
njn607adfc2003-09-30 14:15:44 +0000445 Int i, nc = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000446 Bool neg = False;
447 Char *digits = "0123456789ABCDEF";
sewardj78e3cd92002-10-22 04:45:48 +0000448 UInt ret = 0;
449
sewardjde4a1d02002-03-22 01:27:54 +0000450 if (base < 2 || base > 16)
sewardj78e3cd92002-10-22 04:45:48 +0000451 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000452
453 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
454 p = - (Long)p;
455 neg = True;
456 }
457
458 if (p == 0)
459 buf[ind++] = '0';
460 else {
461 while (p > 0) {
njn607adfc2003-09-30 14:15:44 +0000462 if (flags & VG_MSG_COMMA && 10 == base &&
463 0 == (ind-nc) % 3 && 0 != ind)
464 {
465 buf[ind++] = ',';
466 nc++;
467 }
sewardjde4a1d02002-03-22 01:27:54 +0000468 buf[ind++] = digits[p % base];
469 p /= base;
njn607adfc2003-09-30 14:15:44 +0000470 }
sewardjde4a1d02002-03-22 01:27:54 +0000471 }
472
473 if (neg)
474 buf[ind++] = '-';
475
476 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
477 for(; ind < width; ind++) {
478 vg_assert(ind < 39);
479 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
480 }
481 }
482
483 /* Reverse copy to buffer. */
sewardj78e3cd92002-10-22 04:45:48 +0000484 ret += ind;
njn607adfc2003-09-30 14:15:44 +0000485 for (i = ind -1; i >= 0; i--) {
sewardjde4a1d02002-03-22 01:27:54 +0000486 send(buf[i]);
njn607adfc2003-09-30 14:15:44 +0000487 }
sewardjde4a1d02002-03-22 01:27:54 +0000488 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
sewardj78e3cd92002-10-22 04:45:48 +0000489 for(; ind < width; ind++) {
490 ret++;
njn607adfc2003-09-30 14:15:44 +0000491 send(' '); // Never pad with zeroes on RHS -- changes the value!
sewardj78e3cd92002-10-22 04:45:48 +0000492 }
sewardjde4a1d02002-03-22 01:27:54 +0000493 }
sewardj78e3cd92002-10-22 04:45:48 +0000494 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000495}
496
497
498/* A simple vprintf(). */
sewardj78e3cd92002-10-22 04:45:48 +0000499UInt
sewardjde4a1d02002-03-22 01:27:54 +0000500VG_(vprintf) ( void(*send)(Char), const Char *format, va_list vargs )
501{
sewardj78e3cd92002-10-22 04:45:48 +0000502 UInt ret = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000503 int i;
504 int flags;
505 int width;
506 Bool is_long;
507
508 /* We assume that vargs has already been initialised by the
509 caller, using va_start, and that the caller will similarly
510 clean up with va_end.
511 */
512
513 for (i = 0; format[i] != 0; i++) {
514 if (format[i] != '%') {
515 send(format[i]);
sewardj78e3cd92002-10-22 04:45:48 +0000516 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000517 continue;
518 }
519 i++;
520 /* A '%' has been found. Ignore a trailing %. */
521 if (format[i] == 0)
522 break;
523 if (format[i] == '%') {
524 /* `%%' is replaced by `%'. */
525 send('%');
sewardj78e3cd92002-10-22 04:45:48 +0000526 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000527 continue;
528 }
529 flags = 0;
530 is_long = False;
531 width = 0; /* length of the field. */
sewardj78e3cd92002-10-22 04:45:48 +0000532 if (format[i] == '(') {
533 flags |= VG_MSG_PAREN;
534 i++;
535 }
njn607adfc2003-09-30 14:15:44 +0000536 /* If ',' follows '%', commas will be inserted. */
537 if (format[i] == ',') {
538 flags |= VG_MSG_COMMA;
539 i++;
540 }
sewardjde4a1d02002-03-22 01:27:54 +0000541 /* If '-' follows '%', justify on the left. */
542 if (format[i] == '-') {
543 flags |= VG_MSG_LJUSTIFY;
544 i++;
545 }
546 /* If '0' follows '%', pads will be inserted. */
547 if (format[i] == '0') {
548 flags |= VG_MSG_ZJUSTIFY;
549 i++;
550 }
551 /* Compute the field length. */
552 while (format[i] >= '0' && format[i] <= '9') {
553 width *= 10;
554 width += format[i++] - '0';
555 }
556 while (format[i] == 'l') {
557 i++;
558 is_long = True;
559 }
560
561 switch (format[i]) {
562 case 'd': /* %d */
563 flags |= VG_MSG_SIGNED;
564 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000565 ret += myvprintf_int64(send, flags, 10, width,
566 (ULong)(va_arg (vargs, Long)));
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, Int)));
sewardjde4a1d02002-03-22 01:27:54 +0000570 break;
571 case 'u': /* %u */
572 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000573 ret += myvprintf_int64(send, flags, 10, width,
574 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000575 else
sewardj78e3cd92002-10-22 04:45:48 +0000576 ret += myvprintf_int64(send, flags, 10, width,
577 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000578 break;
579 case 'p': /* %p */
sewardj78e3cd92002-10-22 04:45:48 +0000580 ret += 2;
sewardjde4a1d02002-03-22 01:27:54 +0000581 send('0');
582 send('x');
sewardj78e3cd92002-10-22 04:45:48 +0000583 ret += myvprintf_int64(send, flags, 16, width,
nethercote50397c22004-11-04 18:03:06 +0000584 (ULong)((UWord)va_arg (vargs, void *)));
sewardjde4a1d02002-03-22 01:27:54 +0000585 break;
586 case 'x': /* %x */
587 if (is_long)
sewardj78e3cd92002-10-22 04:45:48 +0000588 ret += myvprintf_int64(send, flags, 16, width,
589 (ULong)(va_arg (vargs, ULong)));
sewardjde4a1d02002-03-22 01:27:54 +0000590 else
sewardj78e3cd92002-10-22 04:45:48 +0000591 ret += myvprintf_int64(send, flags, 16, width,
592 (ULong)(va_arg (vargs, UInt)));
sewardjde4a1d02002-03-22 01:27:54 +0000593 break;
594 case 'c': /* %c */
sewardj78e3cd92002-10-22 04:45:48 +0000595 ret++;
sewardjde4a1d02002-03-22 01:27:54 +0000596 send(va_arg (vargs, int));
597 break;
598 case 's': case 'S': { /* %s */
599 char *str = va_arg (vargs, char *);
600 if (str == (char*) 0) str = "(null)";
sewardj78e3cd92002-10-22 04:45:48 +0000601 ret += myvprintf_str(send, flags, width, str, format[i]=='S');
sewardjde4a1d02002-03-22 01:27:54 +0000602 break;
sewardj78e3cd92002-10-22 04:45:48 +0000603 }
604 case 'y': { /* %y - print symbol */
605 Char buf[100];
606 Char *cp = buf;
607 Addr a = va_arg(vargs, Addr);
608
609 if (flags & VG_MSG_PAREN)
610 *cp++ = '(';
sewardj6e008cb2002-12-15 13:11:39 +0000611 if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
sewardj78e3cd92002-10-22 04:45:48 +0000612 if (flags & VG_MSG_PAREN) {
613 cp += VG_(strlen)(cp);
614 *cp++ = ')';
615 *cp = '\0';
616 }
617 ret += myvprintf_str(send, flags, width, buf, 0);
618 }
619
620 break;
621 }
sewardjde4a1d02002-03-22 01:27:54 +0000622 default:
623 break;
624 }
625 }
sewardj78e3cd92002-10-22 04:45:48 +0000626 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000627}
628
629
630/* A general replacement for printf(). Note that only low-level
631 debugging info should be sent via here. The official route is to
632 to use vg_message(). This interface is deprecated.
633*/
634static char myprintf_buf[100];
635static int n_myprintf_buf;
636
637static void add_to_myprintf_buf ( Char c )
638{
639 if (n_myprintf_buf >= 100-10 /*paranoia*/ ) {
nethercotef8548672004-06-21 12:42:35 +0000640 if (VG_(clo_log_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000641 VG_(send_bytes_to_logging_sink)(
642 myprintf_buf, VG_(strlen)(myprintf_buf) );
sewardj73cf3bc2002-11-03 03:20:15 +0000643 }
sewardjde4a1d02002-03-22 01:27:54 +0000644 n_myprintf_buf = 0;
645 myprintf_buf[n_myprintf_buf] = 0;
646 }
647 myprintf_buf[n_myprintf_buf++] = c;
648 myprintf_buf[n_myprintf_buf] = 0;
649}
650
sewardj78e3cd92002-10-22 04:45:48 +0000651UInt VG_(printf) ( const char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000652{
sewardj78e3cd92002-10-22 04:45:48 +0000653 UInt ret;
sewardjde4a1d02002-03-22 01:27:54 +0000654 va_list vargs;
655 va_start(vargs,format);
656
657 n_myprintf_buf = 0;
658 myprintf_buf[n_myprintf_buf] = 0;
sewardj78e3cd92002-10-22 04:45:48 +0000659 ret = VG_(vprintf) ( add_to_myprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000660
nethercotef8548672004-06-21 12:42:35 +0000661 if (n_myprintf_buf > 0 && VG_(clo_log_fd) >= 0) {
sewardj570f8902002-11-03 11:44:36 +0000662 VG_(send_bytes_to_logging_sink)( myprintf_buf, n_myprintf_buf );
sewardj73cf3bc2002-11-03 03:20:15 +0000663 }
sewardjde4a1d02002-03-22 01:27:54 +0000664
665 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000666
667 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000668}
669
sewardjde4a1d02002-03-22 01:27:54 +0000670/* A general replacement for sprintf(). */
thughes4ad52d02004-06-27 17:37:21 +0000671
672static Char *vg_sprintf_ptr;
673
674static void add_to_vg_sprintf_buf ( Char c )
675{
676 *vg_sprintf_ptr++ = c;
677}
678
sewardj78e3cd92002-10-22 04:45:48 +0000679UInt VG_(sprintf) ( Char* buf, Char *format, ... )
sewardjde4a1d02002-03-22 01:27:54 +0000680{
sewardj05bcdcb2003-05-18 10:05:38 +0000681 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000682 va_list vargs;
thughes4ad52d02004-06-27 17:37:21 +0000683
684 vg_sprintf_ptr = buf;
685
sewardjde4a1d02002-03-22 01:27:54 +0000686 va_start(vargs,format);
687
sewardj78e3cd92002-10-22 04:45:48 +0000688 ret = VG_(vprintf) ( add_to_vg_sprintf_buf, format, vargs );
sewardjde4a1d02002-03-22 01:27:54 +0000689 add_to_vg_sprintf_buf(0);
690
691 va_end(vargs);
sewardj78e3cd92002-10-22 04:45:48 +0000692
693 vg_assert(VG_(strlen)(buf) == ret);
694 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000695}
696
697
698/* ---------------------------------------------------------------------
699 Misc str* functions.
700 ------------------------------------------------------------------ */
701
702Bool VG_(isspace) ( Char c )
703{
704 return (c == ' ' || c == '\n' || c == '\t' || c == 0);
705}
706
njn7cf0bd32002-06-08 13:36:03 +0000707Bool VG_(isdigit) ( Char c )
708{
709 return (c >= '0' && c <= '9');
710}
sewardjde4a1d02002-03-22 01:27:54 +0000711
712Int VG_(strlen) ( const Char* str )
713{
714 Int i = 0;
715 while (str[i] != 0) i++;
716 return i;
717}
718
719
720Long VG_(atoll) ( Char* str )
721{
722 Bool neg = False;
723 Long n = 0;
724 if (*str == '-') { str++; neg = True; };
725 while (*str >= '0' && *str <= '9') {
726 n = 10*n + (Long)(*str - '0');
727 str++;
728 }
729 if (neg) n = -n;
730 return n;
731}
732
733
njn25e49d8e72002-09-23 09:36:25 +0000734Long VG_(atoll16) ( Char* str )
sewardja70ca3f2002-05-30 01:22:20 +0000735{
736 Bool neg = False;
737 Long n = 0;
738 if (*str == '-') { str++; neg = True; };
739 while (True) {
740 if (*str >= '0' && *str <= '9') {
njn25e49d8e72002-09-23 09:36:25 +0000741 n = 16*n + (Long)(*str - '0');
sewardja70ca3f2002-05-30 01:22:20 +0000742 }
743 else
njn25e49d8e72002-09-23 09:36:25 +0000744 if (*str >= 'A' && *str <= 'F') {
745 n = 16*n + (Long)((*str - 'A') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000746 }
747 else
njn25e49d8e72002-09-23 09:36:25 +0000748 if (*str >= 'a' && *str <= 'f') {
749 n = 16*n + (Long)((*str - 'a') + 10);
750 }
751 else {
752 break;
753 }
754 str++;
755 }
756 if (neg) n = -n;
757 return n;
758}
759
760Long VG_(atoll36) ( UInt base, Char* str )
761{
762 Bool neg = False;
763 Long n = 0;
764 vg_assert(base >= 2 && base <= 36);
765 if (*str == '-') { str++; neg = True; };
766 while (True) {
sewardj05bcdcb2003-05-18 10:05:38 +0000767 if (*str >= '0'
768 && *str <= (Char)('9' - (10 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000769 n = base*n + (Long)(*str - '0');
770 }
771 else
sewardj05bcdcb2003-05-18 10:05:38 +0000772 if (base > 10 && *str >= 'A'
773 && *str <= (Char)('Z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000774 n = base*n + (Long)((*str - 'A') + 10);
775 }
776 else
sewardj05bcdcb2003-05-18 10:05:38 +0000777 if (base > 10 && *str >= 'a'
778 && *str <= (Char)('z' - (36 - base))) {
njn25e49d8e72002-09-23 09:36:25 +0000779 n = base*n + (Long)((*str - 'a') + 10);
sewardja70ca3f2002-05-30 01:22:20 +0000780 }
781 else {
782 break;
783 }
784 str++;
785 }
786 if (neg) n = -n;
787 return n;
788}
789
790
sewardjde4a1d02002-03-22 01:27:54 +0000791Char* VG_(strcat) ( Char* dest, const Char* src )
792{
793 Char* dest_orig = dest;
794 while (*dest) dest++;
795 while (*src) *dest++ = *src++;
796 *dest = 0;
797 return dest_orig;
798}
799
800
801Char* VG_(strncat) ( Char* dest, const Char* src, Int n )
802{
803 Char* dest_orig = dest;
804 while (*dest) dest++;
805 while (*src && n > 0) { *dest++ = *src++; n--; }
806 *dest = 0;
807 return dest_orig;
808}
809
810
811Char* VG_(strpbrk) ( const Char* s, const Char* accept )
812{
813 const Char* a;
814 while (*s) {
815 a = accept;
816 while (*a)
817 if (*a++ == *s)
818 return (Char *) s;
819 s++;
820 }
821 return NULL;
822}
823
824
825Char* VG_(strcpy) ( Char* dest, const Char* src )
826{
827 Char* dest_orig = dest;
828 while (*src) *dest++ = *src++;
829 *dest = 0;
830 return dest_orig;
831}
832
833
834/* Copy bytes, not overrunning the end of dest and always ensuring
835 zero termination. */
836void VG_(strncpy_safely) ( Char* dest, const Char* src, Int ndest )
837{
838 Int i;
839 vg_assert(ndest > 0);
840 i = 0;
841 dest[i] = 0;
842 while (True) {
843 if (src[i] == 0) return;
844 if (i >= ndest-1) return;
845 dest[i] = src[i];
846 i++;
847 dest[i] = 0;
848 }
849}
850
851
njn25e49d8e72002-09-23 09:36:25 +0000852Char* VG_(strncpy) ( Char* dest, const Char* src, Int ndest )
sewardjde4a1d02002-03-22 01:27:54 +0000853{
njn25e49d8e72002-09-23 09:36:25 +0000854 Int i = 0;
855 while (True) {
856 if (i >= ndest) return dest; /* reached limit */
857 dest[i] = src[i];
858 if (src[i++] == 0) {
859 /* reached NUL; pad rest with zeroes as required */
860 while (i < ndest) dest[i++] = 0;
861 return dest;
862 }
863 }
sewardjde4a1d02002-03-22 01:27:54 +0000864}
865
866
867Int VG_(strcmp) ( const Char* s1, const Char* s2 )
868{
869 while (True) {
870 if (*s1 == 0 && *s2 == 0) return 0;
871 if (*s1 == 0) return -1;
872 if (*s2 == 0) return 1;
873
874 if (*(UChar*)s1 < *(UChar*)s2) return -1;
875 if (*(UChar*)s1 > *(UChar*)s2) return 1;
876
877 s1++; s2++;
878 }
879}
880
881
882Int VG_(strcmp_ws) ( const Char* s1, const Char* s2 )
883{
884 while (True) {
885 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
886 if (VG_(isspace)(*s1)) return -1;
887 if (VG_(isspace)(*s2)) return 1;
888
889 if (*(UChar*)s1 < *(UChar*)s2) return -1;
890 if (*(UChar*)s1 > *(UChar*)s2) return 1;
891
892 s1++; s2++;
893 }
894}
895
896
897Int VG_(strncmp) ( const Char* s1, const Char* s2, Int nmax )
898{
899 Int n = 0;
900 while (True) {
901 if (n >= nmax) return 0;
902 if (*s1 == 0 && *s2 == 0) return 0;
903 if (*s1 == 0) return -1;
904 if (*s2 == 0) return 1;
905
906 if (*(UChar*)s1 < *(UChar*)s2) return -1;
907 if (*(UChar*)s1 > *(UChar*)s2) return 1;
908
909 s1++; s2++; n++;
910 }
911}
912
913
914Int VG_(strncmp_ws) ( const Char* s1, const Char* s2, Int nmax )
915{
916 Int n = 0;
917 while (True) {
918 if (n >= nmax) return 0;
919 if (VG_(isspace)(*s1) && VG_(isspace)(*s2)) return 0;
920 if (VG_(isspace)(*s1)) return -1;
921 if (VG_(isspace)(*s2)) return 1;
922
923 if (*(UChar*)s1 < *(UChar*)s2) return -1;
924 if (*(UChar*)s1 > *(UChar*)s2) return 1;
925
926 s1++; s2++; n++;
927 }
928}
929
930
931Char* VG_(strstr) ( const Char* haystack, Char* needle )
932{
sewardj3984b852002-05-12 03:00:17 +0000933 Int n;
934 if (haystack == NULL)
935 return NULL;
936 n = VG_(strlen)(needle);
sewardjde4a1d02002-03-22 01:27:54 +0000937 while (True) {
938 if (haystack[0] == 0)
939 return NULL;
940 if (VG_(strncmp)(haystack, needle, n) == 0)
941 return (Char*)haystack;
942 haystack++;
943 }
944}
945
946
947Char* VG_(strchr) ( const Char* s, Char c )
948{
949 while (True) {
950 if (*s == c) return (Char*)s;
951 if (*s == 0) return NULL;
952 s++;
953 }
954}
955
956
thughesc0b63de2004-06-13 09:55:22 +0000957Char* VG_(strrchr) ( const Char* s, Char c )
958{
959 Int n = VG_(strlen)(s);
960 while (--n > 0) {
961 if (s[n] == c) return (Char*)s + n;
962 }
963 return NULL;
964}
965
966
sewardj7ab2aca2002-10-20 19:40:32 +0000967void* VG_(memcpy) ( void *dest, const void *src, Int sz )
968{
969 const Char *s = (const Char *)src;
970 Char *d = (Char *)dest;
971 vg_assert(sz >= 0);
972
973 while (sz--)
974 *d++ = *s++;
975
976 return dest;
977}
978
979
980void* VG_(memset) ( void *dest, Int c, Int sz )
981{
982 Char *d = (Char *)dest;
983 vg_assert(sz >= 0);
984
985 while (sz--)
986 *d++ = c;
987
988 return dest;
989}
990
njn6d68e792003-02-24 10:49:08 +0000991Int VG_(memcmp) ( const void* s1, const void* s2, Int n )
992{
993 Int res;
njnfa4690b2003-02-24 21:43:05 +0000994 UChar a0;
995 UChar b0;
njn6d68e792003-02-24 10:49:08 +0000996 vg_assert(n >= 0);
997
998 while (n != 0) {
njnfa4690b2003-02-24 21:43:05 +0000999 a0 = ((UChar *) s1)[0];
1000 b0 = ((UChar *) s2)[0];
njn6d68e792003-02-24 10:49:08 +00001001 s1 += 1;
1002 s2 += 1;
1003 res = a0 - b0;
1004 if (res != 0)
1005 return res;
1006 n -= 1;
1007 }
1008 return 0;
1009}
sewardj7ab2aca2002-10-20 19:40:32 +00001010
sewardjde4a1d02002-03-22 01:27:54 +00001011Char VG_(toupper) ( Char c )
1012{
1013 if (c >= 'a' && c <= 'z')
1014 return c + ('A' - 'a');
1015 else
1016 return c;
1017}
1018
1019
njn25e49d8e72002-09-23 09:36:25 +00001020/* Inline just for the wrapper VG_(strdup) below */
1021__inline__ Char* VG_(arena_strdup) ( ArenaId aid, const Char* s )
sewardjde4a1d02002-03-22 01:27:54 +00001022{
njn25e49d8e72002-09-23 09:36:25 +00001023 Int i;
fitzhardingea7728472003-12-16 01:48:38 +00001024 Int len;
1025 Char* res;
1026
1027 if (s == NULL)
1028 return NULL;
1029
1030 len = VG_(strlen)(s) + 1;
1031 res = VG_(arena_malloc) (aid, len);
1032
njn25e49d8e72002-09-23 09:36:25 +00001033 for (i = 0; i < len; i++)
1034 res[i] = s[i];
1035 return res;
sewardjde4a1d02002-03-22 01:27:54 +00001036}
1037
nethercote7cc9c232004-01-21 15:08:04 +00001038/* Wrapper to avoid exposing tools to ArenaId's */
njn25e49d8e72002-09-23 09:36:25 +00001039Char* VG_(strdup) ( const Char* s )
1040{
nethercote60f5b822004-01-26 17:24:42 +00001041 return VG_(arena_strdup) ( VG_AR_TOOL, s );
njn25e49d8e72002-09-23 09:36:25 +00001042}
sewardjde4a1d02002-03-22 01:27:54 +00001043
1044/* ---------------------------------------------------------------------
1045 A simple string matching routine, purloined from Hugs98.
1046 `*' matches any sequence of zero or more characters
1047 `?' matches any single character exactly
1048 `\c' matches the character c only (ignoring special chars)
1049 c matches the character c only
1050 ------------------------------------------------------------------ */
1051
1052/* Keep track of recursion depth. */
1053static Int recDepth;
1054
fitzhardinge98abfc72003-12-16 02:05:15 +00001055static Bool string_match_wrk ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001056{
sewardje54b69d2003-07-06 01:14:42 +00001057 vg_assert(recDepth >= 0 && recDepth < 500);
sewardjde4a1d02002-03-22 01:27:54 +00001058 recDepth++;
1059 for (;;) {
1060 switch (*pat) {
1061 case '\0' : return (*str=='\0');
1062 case '*' : do {
njn4ba5a792002-09-30 10:23:54 +00001063 if (string_match_wrk(pat+1,str)) {
sewardjde4a1d02002-03-22 01:27:54 +00001064 recDepth--;
1065 return True;
1066 }
1067 } while (*str++);
1068 recDepth--;
1069 return False;
1070 case '?' : if (*str++=='\0') {
1071 recDepth--;
1072 return False;
1073 }
1074 pat++;
1075 break;
1076 case '\\' : if (*++pat == '\0') {
1077 recDepth--;
1078 return False; /* spurious trailing \ in pattern */
1079 }
1080 /* falls through to ... */
1081 default : if (*pat++ != *str++) {
1082 recDepth--;
1083 return False;
1084 }
1085 break;
1086 }
1087 }
1088}
1089
fitzhardinge98abfc72003-12-16 02:05:15 +00001090Bool VG_(string_match) ( const Char* pat, const Char* str )
sewardjde4a1d02002-03-22 01:27:54 +00001091{
1092 Bool b;
1093 recDepth = 0;
njn4ba5a792002-09-30 10:23:54 +00001094 b = string_match_wrk ( pat, str );
sewardjde4a1d02002-03-22 01:27:54 +00001095 /*
1096 VG_(printf)("%s %s %s\n",
1097 b?"TRUE ":"FALSE", pat, str);
1098 */
1099 return b;
1100}
1101
1102
1103/* ---------------------------------------------------------------------
1104 Assertery.
1105 ------------------------------------------------------------------ */
1106
jsgf855d93d2003-10-13 22:26:55 +00001107/* Fake up an ExeContext which is of our actual real CPU state, so we
1108 can print a stack trace. This isn't terribly useful in the case
1109 where we were killed by a signal, since we just get a backtrace
1110 into the signal handler. Also, it could be somewhat risky if we
1111 actully got the panic/exception within the execontext/stack
1112 dump/symtab code. But it's better than nothing. */
1113static inline ExeContext *get_real_execontext(Addr ret)
1114{
1115 ExeContext *ec;
nethercote856e5872004-10-25 20:44:09 +00001116 Addr sp, fp;
nethercote759dda32004-08-07 18:16:56 +00001117 Addr stacktop, sigstack_low, sigstack_high;
jsgf855d93d2003-10-13 22:26:55 +00001118
nethercote856e5872004-10-25 20:44:09 +00001119 ARCH_GET_REAL_STACK_PTR(sp);
1120 ARCH_GET_REAL_FRAME_PTR(fp);
nethercote820bd8c2004-09-07 23:04:49 +00001121 stacktop = VG_(valgrind_last);
nethercote759dda32004-08-07 18:16:56 +00001122 VG_(get_sigstack_bounds)( &sigstack_low, &sigstack_high );
nethercote856e5872004-10-25 20:44:09 +00001123 if (sp >= sigstack_low && sp < sigstack_high)
nethercote759dda32004-08-07 18:16:56 +00001124 stacktop = sigstack_high;
jsgf855d93d2003-10-13 22:26:55 +00001125
nethercote856e5872004-10-25 20:44:09 +00001126 ec = VG_(get_ExeContext2)(ret, fp, sp, stacktop);
jsgf855d93d2003-10-13 22:26:55 +00001127
1128 return ec;
1129}
1130
njne427a662002-10-02 11:08:25 +00001131__attribute__ ((noreturn))
thughes5876d552004-09-26 18:44:06 +00001132static void report_and_quit ( const Char* report, ExeContext *ec )
njne427a662002-10-02 11:08:25 +00001133{
thughes5876d552004-09-26 18:44:06 +00001134 if (ec == NULL)
1135 ec = get_real_execontext((Addr)__builtin_return_address(0));
1136
jsgf855d93d2003-10-13 22:26:55 +00001137 VG_(pp_ExeContext)(ec);
1138
njne427a662002-10-02 11:08:25 +00001139 VG_(pp_sched_status)();
sewardj366ee1e2003-04-26 22:36:42 +00001140 VG_(printf)("\n");
1141 VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
1142 VG_(printf)("It contains workarounds to several common problems.\n");
1143 VG_(printf)("\n");
1144 VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
1145 report);
1146 VG_(printf)("In the bug report, send all the above text, the valgrind\n");
sewardj96330bd2003-04-27 23:46:21 +00001147 VG_(printf)("version, and what Linux distro you are using. Thanks.\n\n");
njne427a662002-10-02 11:08:25 +00001148 VG_(exit)(1);
1149}
1150
1151__attribute__ ((noreturn))
daywalker3222e0a2003-09-18 01:39:50 +00001152static void assert_fail ( const Char* expr, const Char* name, const Char* report,
1153 const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001154{
sewardj018f7622002-05-15 21:13:39 +00001155 static Bool entered = False;
1156 if (entered)
1157 VG_(exit)(2);
1158 entered = True;
sewardjde4a1d02002-03-22 01:27:54 +00001159 VG_(printf)("\n%s: %s:%d (%s): Assertion `%s' failed.\n",
njne427a662002-10-02 11:08:25 +00001160 name, file, line, fn, expr );
thughes5876d552004-09-26 18:44:06 +00001161 report_and_quit(report, NULL);
sewardjde4a1d02002-03-22 01:27:54 +00001162}
1163
njn94065fd2004-11-22 19:26:27 +00001164void VG_(tool_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
sewardjde4a1d02002-03-22 01:27:54 +00001165{
njnd04b7c62002-10-03 14:05:52 +00001166 assert_fail(expr, VG_(details).name, VG_(details).bug_reports_to,
njne427a662002-10-02 11:08:25 +00001167 file, line, fn);
1168}
1169
daywalker3222e0a2003-09-18 01:39:50 +00001170void VG_(core_assert_fail) ( const Char* expr, const Char* file, Int line, const Char* fn )
njne427a662002-10-02 11:08:25 +00001171{
nethercote421281e2003-11-20 16:20:55 +00001172 assert_fail(expr, "valgrind", VG_BUGS_TO, file, line, fn);
njne427a662002-10-02 11:08:25 +00001173}
1174
1175__attribute__ ((noreturn))
thughes671ce382004-09-27 18:57:08 +00001176static void panic ( Char* name, Char* report, Char* str, ExeContext *ec )
njne427a662002-10-02 11:08:25 +00001177{
1178 VG_(printf)("\n%s: the `impossible' happened:\n %s\n", name, str);
sewardjde4a1d02002-03-22 01:27:54 +00001179 VG_(printf)("Basic block ctr is approximately %llu\n", VG_(bbs_done) );
thughes671ce382004-09-27 18:57:08 +00001180 report_and_quit(report, ec);
sewardjde4a1d02002-03-22 01:27:54 +00001181}
1182
njne427a662002-10-02 11:08:25 +00001183void VG_(core_panic) ( Char* str )
njn25e49d8e72002-09-23 09:36:25 +00001184{
thughes5876d552004-09-26 18:44:06 +00001185 panic("valgrind", VG_BUGS_TO, str, NULL);
1186}
1187
1188void VG_(core_panic_at) ( Char* str, ExeContext *ec )
1189{
1190 panic("valgrind", VG_BUGS_TO, str, ec);
njn25e49d8e72002-09-23 09:36:25 +00001191}
1192
njn67993252004-11-22 18:02:32 +00001193void VG_(tool_panic) ( Char* str )
njne427a662002-10-02 11:08:25 +00001194{
thughes5876d552004-09-26 18:44:06 +00001195 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njne427a662002-10-02 11:08:25 +00001196}
sewardjde4a1d02002-03-22 01:27:54 +00001197
njn13f02932003-04-30 20:23:58 +00001198
sewardjde4a1d02002-03-22 01:27:54 +00001199/* ---------------------------------------------------------------------
1200 Primitive support for reading files.
1201 ------------------------------------------------------------------ */
1202
jsgf855d93d2003-10-13 22:26:55 +00001203static inline Bool fd_exists(Int fd)
1204{
1205 struct vki_stat st;
1206
1207 return VG_(fstat)(fd, &st) == 0;
1208}
1209
1210/* Move an fd into the Valgrind-safe range */
1211Int VG_(safe_fd)(Int oldfd)
1212{
1213 Int newfd;
1214
thughesad1c9562004-06-26 11:27:52 +00001215 vg_assert(VG_(fd_hard_limit) != -1);
fitzhardingeb791a192003-12-18 07:22:44 +00001216
thughesad1c9562004-06-26 11:27:52 +00001217 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
jsgf855d93d2003-10-13 22:26:55 +00001218 if (newfd != -1)
1219 VG_(close)(oldfd);
1220
1221 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
1222
thughesad1c9562004-06-26 11:27:52 +00001223 vg_assert(newfd >= VG_(fd_hard_limit));
jsgf855d93d2003-10-13 22:26:55 +00001224 return newfd;
1225}
1226
1227
1228
sewardjde4a1d02002-03-22 01:27:54 +00001229/* Returns -1 on failure. */
njn25e49d8e72002-09-23 09:36:25 +00001230Int VG_(open) ( const Char* pathname, Int flags, Int mode )
1231{
sewardjde4a1d02002-03-22 01:27:54 +00001232 Int fd;
sewardjde4a1d02002-03-22 01:27:54 +00001233
njn25e49d8e72002-09-23 09:36:25 +00001234 /* (old comment, not sure if it still applies NJN 2002-sep-09) */
sewardjde4a1d02002-03-22 01:27:54 +00001235 /* This gets a segmentation fault if pathname isn't a valid file.
1236 I don't know why. It seems like the call to open is getting
1237 intercepted and messed with by glibc ... */
1238 /* fd = open( pathname, O_RDONLY ); */
1239 /* ... so we go direct to the horse's mouth, which seems to work
1240 ok: */
nethercotecf51cc42004-11-04 17:02:42 +00001241 fd = VG_(do_syscall)(__NR_open, (UWord)pathname, flags, mode);
njn4f9c9342002-04-29 16:03:24 +00001242 /* VG_(printf)("result = %d\n", fd); */
jsgff3c3f1a2003-10-14 22:13:28 +00001243 /* return -ve error code */
njn4f9c9342002-04-29 16:03:24 +00001244 return fd;
1245}
sewardjde4a1d02002-03-22 01:27:54 +00001246
jsgf855d93d2003-10-13 22:26:55 +00001247Int VG_(pipe) ( Int fd[2] )
1248{
1249 Int ret = VG_(do_syscall)(__NR_pipe, fd);
1250 return VG_(is_kerror)(ret) ? -1 : 0;
1251}
1252
sewardjde4a1d02002-03-22 01:27:54 +00001253void VG_(close) ( Int fd )
1254{
jsgf855d93d2003-10-13 22:26:55 +00001255 VG_(do_syscall)(__NR_close, fd);
sewardjde4a1d02002-03-22 01:27:54 +00001256}
1257
1258
1259Int VG_(read) ( Int fd, void* buf, Int count)
1260{
1261 Int res;
1262 /* res = read( fd, buf, count ); */
nethercotecf51cc42004-11-04 17:02:42 +00001263 res = VG_(do_syscall)(__NR_read, fd, (UWord)buf, count);
jsgf855d93d2003-10-13 22:26:55 +00001264 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001265 return res;
1266}
1267
jsgf855d93d2003-10-13 22:26:55 +00001268Int VG_(write) ( Int fd, const void* buf, Int count)
sewardjde4a1d02002-03-22 01:27:54 +00001269{
1270 Int res;
1271 /* res = write( fd, buf, count ); */
nethercotecf51cc42004-11-04 17:02:42 +00001272 res = VG_(do_syscall)(__NR_write, fd, (UWord)buf, count);
jsgf855d93d2003-10-13 22:26:55 +00001273 /* return -ERRNO on error */
sewardjde4a1d02002-03-22 01:27:54 +00001274 return res;
1275}
1276
nethercote5b9fafd2004-11-04 18:39:22 +00001277OffT VG_(lseek) ( Int fd, OffT offset, Int whence)
rjwalshf5f536f2003-11-17 17:45:00 +00001278{
1279 Int res;
1280 /* res = lseek( fd, offset, whence ); */
nethercote5b9fafd2004-11-04 18:39:22 +00001281 res = VG_(do_syscall)(__NR_lseek, fd, offset, whence);
rjwalshf5f536f2003-11-17 17:45:00 +00001282 if (VG_(is_kerror)(res)) res = -1;
1283 return res;
1284}
1285
sewardjb3586202002-05-09 17:38:13 +00001286Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
1287{
1288 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001289 res = VG_(do_syscall)(__NR_stat, (UWord)file_name, (UWord)buf);
fitzhardingee1c06d82003-10-30 07:21:44 +00001290 return res; /* return -ve error */
njn41557122002-10-14 09:25:37 +00001291}
1292
jsgf855d93d2003-10-13 22:26:55 +00001293Int VG_(fstat) ( Int fd, struct vki_stat* buf )
1294{
1295 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001296 res = VG_(do_syscall)(__NR_fstat, fd, (UWord)buf);
jsgf855d93d2003-10-13 22:26:55 +00001297 return VG_(is_kerror)(res) ? (-1) : 0;
1298}
1299
1300Int VG_(dup2) ( Int oldfd, Int newfd )
1301{
1302 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001303 res = VG_(do_syscall)(__NR_dup2, oldfd, newfd);
jsgf855d93d2003-10-13 22:26:55 +00001304 return VG_(is_kerror)(res) ? (-1) : res;
1305}
1306
njn41557122002-10-14 09:25:37 +00001307Int VG_(rename) ( Char* old_name, Char* new_name )
1308{
1309 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001310 res = VG_(do_syscall)(__NR_rename, (UWord)old_name, (UWord)new_name);
njn41557122002-10-14 09:25:37 +00001311 return VG_(is_kerror)(res) ? (-1) : 0;
sewardjb3586202002-05-09 17:38:13 +00001312}
1313
njn4aca2d22002-10-04 10:29:38 +00001314Int VG_(unlink) ( Char* file_name )
1315{
1316 Int res;
nethercotecf51cc42004-11-04 17:02:42 +00001317 res = VG_(do_syscall)(__NR_unlink, (UWord)file_name);
njn41557122002-10-14 09:25:37 +00001318 return VG_(is_kerror)(res) ? (-1) : 0;
njn4aca2d22002-10-04 10:29:38 +00001319}
1320
njn13f02932003-04-30 20:23:58 +00001321/* Nb: we do not allow the Linux extension which malloc()s memory for the
1322 buffer if buf==NULL, because we don't want Linux calling malloc() */
nethercote928a5f72004-11-03 18:10:37 +00001323Char* VG_(getcwd) ( Char* buf, SizeT size )
njn13f02932003-04-30 20:23:58 +00001324{
njnc6168192004-11-29 13:54:10 +00001325 Word res;
njn13f02932003-04-30 20:23:58 +00001326 vg_assert(buf != NULL);
nethercotecf51cc42004-11-04 17:02:42 +00001327 res = VG_(do_syscall)(__NR_getcwd, (UWord)buf, size);
njn13f02932003-04-30 20:23:58 +00001328 return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
1329}
1330
njn99ccf082003-09-30 13:51:23 +00001331/* Alternative version that does allocate the memory. Easier to use. */
1332Bool VG_(getcwd_alloc) ( Char** out )
1333{
nethercote928a5f72004-11-03 18:10:37 +00001334 SizeT size = 4;
njn99ccf082003-09-30 13:51:23 +00001335
1336 *out = NULL;
1337 while (True) {
1338 *out = VG_(malloc)(size);
1339 if (NULL == VG_(getcwd)(*out, size)) {
1340 VG_(free)(*out);
1341 if (size > 65535)
1342 return False;
1343 size *= 2;
1344 } else {
1345 return True;
1346 }
1347 }
1348}
1349
njn13f02932003-04-30 20:23:58 +00001350
1351/* ---------------------------------------------------------------------
1352 Misc functions looking for a proper home.
1353 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001354
nethercoteff9721d2004-01-26 17:10:01 +00001355/* clone the environment */
nethercote85cdd342004-08-01 22:36:40 +00001356static Char **env_clone ( Char **oldenv )
nethercoteff9721d2004-01-26 17:10:01 +00001357{
1358 Char **oldenvp;
1359 Char **newenvp;
1360 Char **newenv;
1361 Int envlen;
1362
1363 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
1364
1365 envlen = oldenvp - oldenv + 1;
1366
1367 newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1368
1369 oldenvp = oldenv;
1370 newenvp = newenv;
1371
1372 while (oldenvp && *oldenvp) {
1373 *newenvp++ = *oldenvp++;
1374 }
1375
1376 *newenvp = *oldenvp;
1377
1378 return newenv;
1379}
1380
fitzhardinge98abfc72003-12-16 02:05:15 +00001381void VG_(env_unsetenv) ( Char **env, const Char *varname )
1382{
1383 Char **from;
1384 Char **to = NULL;
1385 Int len = VG_(strlen)(varname);
1386
1387 for(from = to = env; from && *from; from++) {
1388 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
1389 *to = *from;
1390 to++;
1391 }
1392 }
1393 *to = *from;
1394}
1395
1396/* set the environment; returns the old env if a new one was allocated */
1397Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
1398{
1399 Char **env = (*envp);
1400 Char **cpp;
1401 Int len = VG_(strlen)(varname);
1402 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, len + VG_(strlen)(val) + 2);
1403 Char **oldenv = NULL;
1404
1405 VG_(sprintf)(valstr, "%s=%s", varname, val);
1406
1407 for(cpp = env; cpp && *cpp; cpp++) {
1408 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
1409 *cpp = valstr;
1410 return oldenv;
1411 }
1412 }
1413
1414 if (env == NULL) {
1415 env = VG_(arena_malloc)(VG_AR_CORE, sizeof(Char **) * 2);
1416 env[0] = valstr;
1417 env[1] = NULL;
1418
1419 *envp = env;
1420
1421 } else {
1422 Int envlen = (cpp-env) + 2;
1423 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
1424
1425 for(cpp = newenv; *env; )
1426 *cpp++ = *env++;
1427 *cpp++ = valstr;
1428 *cpp++ = NULL;
1429
1430 oldenv = *envp;
1431
1432 *envp = newenv;
1433 }
1434
1435 return oldenv;
1436}
1437
nethercote85cdd342004-08-01 22:36:40 +00001438/* We do getenv without libc's help by snooping around in
1439 VG_(client_envp) as determined at startup time. */
1440Char *VG_(getenv)(Char *varname)
sewardjde4a1d02002-03-22 01:27:54 +00001441{
1442 Int i, n;
1443 n = VG_(strlen)(varname);
nethercote85cdd342004-08-01 22:36:40 +00001444 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
1445 Char* s = VG_(client_envp)[i];
sewardjde4a1d02002-03-22 01:27:54 +00001446 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
1447 return & s[n+1];
1448 }
1449 }
1450 return NULL;
1451}
1452
rjwalshf5f536f2003-11-17 17:45:00 +00001453/* Support for getrlimit. */
1454Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
1455{
1456 Int res;
1457 /* res = getrlimit( resource, rlim ); */
nethercotecf51cc42004-11-04 17:02:42 +00001458 res = VG_(do_syscall)(__NR_getrlimit, resource, (UWord)rlim);
rjwalshf5f536f2003-11-17 17:45:00 +00001459 if(VG_(is_kerror)(res)) res = -1;
1460 return res;
1461}
1462
1463
fitzhardingef0046f22003-12-18 02:39:22 +00001464/* Support for setrlimit. */
1465Int VG_(setrlimit) (Int resource, struct vki_rlimit *rlim)
1466{
1467 Int res;
1468 /* res = setrlimit( resource, rlim ); */
nethercotecf51cc42004-11-04 17:02:42 +00001469 res = VG_(do_syscall)(__NR_setrlimit, resource, (UWord)rlim);
fitzhardingef0046f22003-12-18 02:39:22 +00001470 if(VG_(is_kerror)(res)) res = -1;
1471 return res;
1472}
1473
1474
rjwalshf5f536f2003-11-17 17:45:00 +00001475/* Support for getdents. */
1476Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
1477{
1478 Int res;
1479 /* res = getdents( fd, dirp, count ); */
nethercotecf51cc42004-11-04 17:02:42 +00001480 res = VG_(do_syscall)(__NR_getdents, fd, (UWord)dirp, count);
rjwalshf5f536f2003-11-17 17:45:00 +00001481 if (VG_(is_kerror)(res)) res = -1;
1482 return res;
1483}
1484
1485/* Support for a readlink. */
1486Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
1487{
1488 Int res;
1489 /* res = readlink( path, buf, bufsiz ); */
nethercotecf51cc42004-11-04 17:02:42 +00001490 res = VG_(do_syscall)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
rjwalshf5f536f2003-11-17 17:45:00 +00001491 if (VG_(is_kerror)(res)) res = -1;
1492 return res;
1493}
1494
sewardjde4a1d02002-03-22 01:27:54 +00001495/* You'd be amazed how many places need to know the current pid. */
1496Int VG_(getpid) ( void )
1497{
1498 Int res;
1499 /* res = getpid(); */
jsgf855d93d2003-10-13 22:26:55 +00001500 res = VG_(do_syscall)(__NR_getpid);
1501 return res;
1502}
1503
1504Int VG_(getpgrp) ( void )
1505{
1506 Int res;
1507 /* res = getpgid(); */
1508 res = VG_(do_syscall)(__NR_getpgrp);
sewardjde4a1d02002-03-22 01:27:54 +00001509 return res;
1510}
1511
sewardj4cf05692002-10-27 20:28:29 +00001512Int VG_(getppid) ( void )
1513{
1514 Int res;
jsgf855d93d2003-10-13 22:26:55 +00001515 res = VG_(do_syscall)(__NR_getppid);
sewardj4cf05692002-10-27 20:28:29 +00001516 return res;
1517}
1518
jsgf855d93d2003-10-13 22:26:55 +00001519Int VG_(setpgid) ( Int pid, Int pgrp )
1520{
1521 return VG_(do_syscall)(__NR_setpgid, pid, pgrp);
1522}
sewardj4cf05692002-10-27 20:28:29 +00001523
nethercote60a96c52004-08-03 13:08:31 +00001524/* Walk through a colon-separated environment variable, and remove the
1525 entries which match remove_pattern. It slides everything down over
1526 the removed entries, and pads the remaining space with '\0'. It
1527 modifies the entries in place (in the client address space), but it
1528 shouldn't matter too much, since we only do this just before an
1529 execve().
1530
1531 This is also careful to mop up any excess ':'s, since empty strings
1532 delimited by ':' are considered to be '.' in a path.
1533*/
1534static void mash_colon_env(Char *varp, const Char *remove_pattern)
1535{
1536 Char *const start = varp;
1537 Char *entry_start = varp;
1538 Char *output = varp;
1539
1540 if (varp == NULL)
1541 return;
1542
1543 while(*varp) {
1544 if (*varp == ':') {
1545 Char prev;
1546 Bool match;
1547
1548 /* This is a bit subtle: we want to match against the entry
1549 we just copied, because it may have overlapped with
1550 itself, junking the original. */
1551
1552 prev = *output;
1553 *output = '\0';
1554
1555 match = VG_(string_match)(remove_pattern, entry_start);
1556
1557 *output = prev;
1558
1559 if (match) {
1560 output = entry_start;
1561 varp++; /* skip ':' after removed entry */
1562 } else
1563 entry_start = output+1; /* entry starts after ':' */
1564 }
1565
1566 *output++ = *varp++;
1567 }
1568
1569 /* match against the last entry */
1570 if (VG_(string_match)(remove_pattern, entry_start)) {
1571 output = entry_start;
1572 if (output > start) {
1573 /* remove trailing ':' */
1574 output--;
1575 vg_assert(*output == ':');
1576 }
1577 }
1578
1579 /* pad out the left-overs with '\0' */
1580 while(output < varp)
1581 *output++ = '\0';
1582}
1583
1584
1585// Removes all the Valgrind-added stuff from the passed environment. Used
1586// when starting child processes, so they don't see that added stuff.
1587void VG_(env_remove_valgrind_env_stuff)(Char** envp)
1588{
1589 Int i;
1590 Char* ld_preload_str = NULL;
1591 Char* ld_library_path_str = NULL;
1592 Char* buf;
1593
1594 // Find LD_* variables
1595 for (i = 0; envp[i] != NULL; i++) {
1596 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
1597 ld_preload_str = &envp[i][11];
1598 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
1599 ld_library_path_str = &envp[i][16];
1600 }
1601
1602 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
1603
1604 // Remove Valgrind-specific entries from LD_*.
1605 VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
1606 mash_colon_env(ld_preload_str, buf);
1607 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
1608 mash_colon_env(ld_preload_str, buf);
1609 VG_(sprintf)(buf, "%s*", VG_(libdir));
1610 mash_colon_env(ld_library_path_str, buf);
1611
1612 // Remove VALGRIND_CLO variable.
1613 VG_(env_unsetenv)(envp, VALGRINDCLO);
1614
1615 // XXX if variable becomes empty, remove it completely?
1616
1617 VG_(arena_free)(VG_AR_CORE, buf);
1618}
1619
sewardje6a25242002-04-21 22:03:07 +00001620/* Return -1 if error, else 0. NOTE does not indicate return code of
1621 child! */
1622Int VG_(system) ( Char* cmd )
1623{
1624 Int pid, res;
sewardje6a25242002-04-21 22:03:07 +00001625 if (cmd == NULL)
1626 return 1;
jsgf855d93d2003-10-13 22:26:55 +00001627 pid = VG_(do_syscall)(__NR_fork);
sewardje6a25242002-04-21 22:03:07 +00001628 if (VG_(is_kerror)(pid))
1629 return -1;
1630 if (pid == 0) {
1631 /* child */
nethercoteff9721d2004-01-26 17:10:01 +00001632 static Char** envp = NULL;
sewardje6a25242002-04-21 22:03:07 +00001633 Char* argv[4];
nethercoteff9721d2004-01-26 17:10:01 +00001634
fitzhardingeb50068f2004-02-24 23:42:55 +00001635 /* restore the DATA rlimit for the child */
1636 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1637
nethercote60a96c52004-08-03 13:08:31 +00001638 envp = env_clone(VG_(client_envp));
1639 VG_(env_remove_valgrind_env_stuff)( envp );
nethercoteff9721d2004-01-26 17:10:01 +00001640
sewardje6a25242002-04-21 22:03:07 +00001641 argv[0] = "/bin/sh";
1642 argv[1] = "-c";
1643 argv[2] = cmd;
1644 argv[3] = 0;
nethercoteff9721d2004-01-26 17:10:01 +00001645
jsgf855d93d2003-10-13 22:26:55 +00001646 (void)VG_(do_syscall)(__NR_execve,
nethercote50397c22004-11-04 18:03:06 +00001647 (UWord)"/bin/sh", (UWord)argv, (UWord)envp);
nethercoteff9721d2004-01-26 17:10:01 +00001648
sewardje6a25242002-04-21 22:03:07 +00001649 /* If we're still alive here, execve failed. */
fitzhardingeabab8392004-03-02 21:38:51 +00001650 VG_(exit)(1);
sewardje6a25242002-04-21 22:03:07 +00001651 } else {
1652 /* parent */
fitzhardingeabab8392004-03-02 21:38:51 +00001653 res = VG_(waitpid)(pid, NULL, 0);
sewardje6a25242002-04-21 22:03:07 +00001654 if (VG_(is_kerror)(res)) {
1655 return -1;
1656 } else {
fitzhardingeabab8392004-03-02 21:38:51 +00001657 return 0;
sewardje6a25242002-04-21 22:03:07 +00001658 }
1659 }
1660}
1661
1662
sewardjde4a1d02002-03-22 01:27:54 +00001663/* ---------------------------------------------------------------------
fitzhardinge66871692004-01-25 03:32:58 +00001664 Support for a millisecond-granularity timer.
sewardj5f07b662002-04-23 16:52:51 +00001665 ------------------------------------------------------------------ */
1666
sewardj5f07b662002-04-23 16:52:51 +00001667UInt VG_(read_millisecond_timer) ( void )
1668{
fitzhardinge426f9e62004-01-25 03:44:18 +00001669 static ULong base = 0;
fitzhardinge66871692004-01-25 03:32:58 +00001670 struct vki_timeval tv_now;
1671 ULong now;
sewardj5f07b662002-04-23 16:52:51 +00001672 Int res;
sewardj5f07b662002-04-23 16:52:51 +00001673
nethercotefbd6ffd2004-11-04 17:10:24 +00001674 res = VG_(do_syscall)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
sewardj5f07b662002-04-23 16:52:51 +00001675
fitzhardinge66871692004-01-25 03:32:58 +00001676 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1677
1678 if (base == 0)
1679 base = now;
sewardj5f07b662002-04-23 16:52:51 +00001680
fitzhardinge66871692004-01-25 03:32:58 +00001681 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +00001682}
1683
1684
sewardj5f07b662002-04-23 16:52:51 +00001685/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +00001686 Primitive support for bagging memory via mmap.
1687 ------------------------------------------------------------------ */
1688
nethercote8b5f40c2004-11-02 13:29:50 +00001689void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who )
sewardjde4a1d02002-03-22 01:27:54 +00001690{
nethercote8b5f40c2004-11-02 13:29:50 +00001691 static SizeT tot_alloc = 0;
sewardj7c2020b2002-09-30 22:56:03 +00001692 void* p;
nethercotec314eba2004-07-15 12:59:41 +00001693 p = VG_(mmap)(0, nBytes,
1694 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
1695 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 0, -1, 0);
fitzhardinge98abfc72003-12-16 02:05:15 +00001696
sewardjde4a1d02002-03-22 01:27:54 +00001697 if (p != ((void*)(-1))) {
nethercotefb583e22004-09-07 23:15:37 +00001698 vg_assert((void*)VG_(valgrind_base) <= p && p <= (void*)VG_(valgrind_last));
nethercote50397c22004-11-04 18:03:06 +00001699 tot_alloc += nBytes;
sewardjde4a1d02002-03-22 01:27:54 +00001700 if (0)
sewardje9047952002-06-05 20:28:33 +00001701 VG_(printf)(
nethercote8b5f40c2004-11-02 13:29:50 +00001702 "get_memory_from_mmap: %llu tot, %llu req = %p .. %p, caller %s\n",
1703 (ULong)tot_alloc, (ULong)nBytes, p, ((char*)p) + nBytes - 1, who );
sewardjde4a1d02002-03-22 01:27:54 +00001704 return p;
1705 }
sewardj7c2020b2002-09-30 22:56:03 +00001706
njn25e49d8e72002-09-23 09:36:25 +00001707 VG_(printf)("\n");
nethercote8b5f40c2004-11-02 13:29:50 +00001708 VG_(printf)("VG_(get_memory_from_mmap): %s's request for %llu bytes failed.\n",
1709 who, (ULong)nBytes);
1710 VG_(printf)("VG_(get_memory_from_mmap): %llu bytes already allocated.\n",
1711 (ULong)tot_alloc);
njn25e49d8e72002-09-23 09:36:25 +00001712 VG_(printf)("\n");
nethercotee757d6e2004-07-10 16:17:52 +00001713 VG_(printf)("Sorry. You could try using a tool that uses less memory;\n");
1714 VG_(printf)("eg. addrcheck instead of memcheck.\n");
njn25e49d8e72002-09-23 09:36:25 +00001715 VG_(printf)("\n");
1716 VG_(exit)(1);
sewardjde4a1d02002-03-22 01:27:54 +00001717}
1718
njn25e49d8e72002-09-23 09:36:25 +00001719/* ---------------------------------------------------------------------
1720 Generally useful...
1721 ------------------------------------------------------------------ */
1722
1723Int VG_(log2) ( Int x )
1724{
1725 Int i;
1726 /* Any more than 32 and we overflow anyway... */
1727 for (i = 0; i < 32; i++) {
1728 if (1 << i == x) return i;
1729 }
1730 return -1;
1731}
1732
1733
njnd3b0c5f2003-09-30 14:43:54 +00001734// Generic shell sort. Like stdlib.h's qsort().
nethercote928a5f72004-11-03 18:10:37 +00001735void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
njnd3b0c5f2003-09-30 14:43:54 +00001736 Int (*compar)(void*, void*) )
1737{
1738 Int incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
1739 9841, 29524, 88573, 265720,
1740 797161, 2391484 };
1741 Int lo = 0;
1742 Int hi = nmemb-1;
1743 Int i, j, h, bigN, hp;
1744
1745 bigN = hi - lo + 1; if (bigN < 2) return;
1746 hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
1747 vg_assert(0 <= hp && hp < 14);
1748
1749 #define SORT \
1750 for ( ; hp >= 0; hp--) { \
1751 h = incs[hp]; \
njn92c54362003-10-15 14:00:35 +00001752 for (i = lo + h; i <= hi; i++) { \
njnd3b0c5f2003-09-30 14:43:54 +00001753 ASSIGN(v,0, a,i); \
1754 j = i; \
njn92c54362003-10-15 14:00:35 +00001755 while (COMPAR(a,(j-h), v,0) > 0) { \
njnd3b0c5f2003-09-30 14:43:54 +00001756 ASSIGN(a,j, a,(j-h)); \
1757 j = j - h; \
1758 if (j <= (lo + h - 1)) break; \
1759 } \
1760 ASSIGN(a,j, v,0); \
njnd3b0c5f2003-09-30 14:43:54 +00001761 } \
1762 }
1763
1764 // Specialised cases
nethercote928a5f72004-11-03 18:10:37 +00001765 if (sizeof(ULong) == size) {
njnd3b0c5f2003-09-30 14:43:54 +00001766
1767 #define ASSIGN(dst, dsti, src, srci) \
1768 (dst)[(dsti)] = (src)[(srci)];
1769
1770 #define COMPAR(dst, dsti, src, srci) \
1771 compar( (void*)(& (dst)[(dsti)]), (void*)(& (src)[(srci)]) )
1772
nethercote928a5f72004-11-03 18:10:37 +00001773 ULong* a = (ULong*)base;
1774 ULong v[1];
1775
1776 SORT;
1777
1778 } else if (sizeof(UInt) == size) {
1779
njnd3b0c5f2003-09-30 14:43:54 +00001780 UInt* a = (UInt*)base;
1781 UInt v[1];
1782
1783 SORT;
1784
1785 } else if (sizeof(UShort) == size) {
1786 UShort* a = (UShort*)base;
1787 UShort v[1];
1788
1789 SORT;
1790
1791 } else if (sizeof(UChar) == size) {
1792 UChar* a = (UChar*)base;
1793 UChar v[1];
1794
1795 SORT;
1796
1797 #undef ASSIGN
1798 #undef COMPAR
1799
1800 // General case
1801 } else {
njn92c54362003-10-15 14:00:35 +00001802 char* a = base;
1803 char v[size]; // will be at least 'size' bytes
njnd3b0c5f2003-09-30 14:43:54 +00001804
1805 #define ASSIGN(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001806 VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
njnd3b0c5f2003-09-30 14:43:54 +00001807
1808 #define COMPAR(dst, dsti, src, srci) \
njn92c54362003-10-15 14:00:35 +00001809 compar( &dst[size*(dsti)], &src[size*(srci)] )
njnd3b0c5f2003-09-30 14:43:54 +00001810
1811 SORT;
1812
1813 #undef ASSIGN
1814 #undef COMPAR
1815 }
1816 #undef SORT
1817}
1818
sewardj73cf3bc2002-11-03 03:20:15 +00001819/* ---------------------------------------------------------------------
1820 Gruesome hackery for connecting to a logging server over the network.
1821 This is all very Linux-kernel specific.
1822 ------------------------------------------------------------------ */
1823
sewardj73cf3bc2002-11-03 03:20:15 +00001824static
1825Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
1826
1827static
1828Int my_socket ( Int domain, Int type, Int protocol );
1829
1830static
1831Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1832 Int addrlen );
1833
1834static
1835UInt my_htonl ( UInt x )
1836{
1837 return
1838 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1839 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1840}
1841
1842static
1843UShort my_htons ( UShort x )
1844{
1845 return
1846 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1847}
1848
1849
1850/* The main function.
1851
1852 Supplied string contains either an ip address "192.168.0.1" or
1853 an ip address and port pair, "192.168.0.1:1500". Parse these,
1854 and return:
1855 -1 if there is a parse error
1856 -2 if no parse error, but specified host:port cannot be opened
1857 the relevant file (socket) descriptor, otherwise.
sewardj4f094a72002-11-05 23:37:35 +00001858 is used.
sewardj73cf3bc2002-11-03 03:20:15 +00001859*/
1860Int VG_(connect_via_socket)( UChar* str )
1861{
1862 Int sd, res;
1863 struct vki_sockaddr_in servAddr;
1864 UInt ip = 0;
sewardj4f094a72002-11-05 23:37:35 +00001865 UShort port = VG_CLO_DEFAULT_LOGPORT;
sewardj73cf3bc2002-11-03 03:20:15 +00001866 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1867 if (!ok)
1868 return -1;
1869
1870 if (0)
1871 VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1872 (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1873 (ip >> 8) & 0xFF, ip & 0xFF,
1874 (UInt)port );
1875
nethercote73b526f2004-10-31 18:48:21 +00001876 servAddr.sin_family = VKI_AF_INET;
sewardj73cf3bc2002-11-03 03:20:15 +00001877 servAddr.sin_addr.s_addr = my_htonl(ip);
1878 servAddr.sin_port = my_htons(port);
1879
1880 /* create socket */
nethercote73b526f2004-10-31 18:48:21 +00001881 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
sewardj73cf3bc2002-11-03 03:20:15 +00001882 if (sd < 0) {
1883 /* this shouldn't happen ... nevertheless */
1884 return -2;
1885 }
1886
1887 /* connect to server */
1888 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
1889 sizeof(servAddr));
1890 if (res < 0) {
1891 /* connection failed */
1892 return -2;
1893 }
1894
1895 return sd;
1896}
1897
1898
1899/* Let d = one or more digits. Accept either:
1900 d.d.d.d or d.d.d.d:d
1901*/
1902Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
1903{
1904# define GET_CH ((*str) ? (*str++) : 0)
1905 UInt ipa, i, j, c, any;
1906 ipa = 0;
1907 for (i = 0; i < 4; i++) {
1908 j = 0;
1909 any = 0;
1910 while (1) {
1911 c = GET_CH;
1912 if (c < '0' || c > '9') break;
1913 j = 10 * j + (int)(c - '0');
1914 any = 1;
1915 }
1916 if (any == 0 || j > 255) goto syntaxerr;
1917 ipa = (ipa << 8) + j;
1918 if (i <= 2 && c != '.') goto syntaxerr;
1919 }
1920 if (c == 0 || c == ':')
1921 *ip_addr = ipa;
1922 if (c == 0) goto ok;
1923 if (c != ':') goto syntaxerr;
1924 j = 0;
1925 any = 0;
1926 while (1) {
1927 c = GET_CH;
1928 if (c < '0' || c > '9') break;
1929 j = j * 10 + (int)(c - '0');
1930 any = 1;
1931 if (j > 65535) goto syntaxerr;
1932 }
1933 if (any == 0 || c != 0) goto syntaxerr;
sewardjd2220672002-11-13 19:41:41 +00001934 if (j < 1024) goto syntaxerr;
sewardj73cf3bc2002-11-03 03:20:15 +00001935 *port = (UShort)j;
1936 ok:
1937 return 1;
1938 syntaxerr:
1939 return 0;
1940# undef GET_CH
1941}
1942
1943
1944static
1945Int my_socket ( Int domain, Int type, Int protocol )
1946{
njnc6168192004-11-29 13:54:10 +00001947// AMD64/Linux doesn't define __NR_socketcall... see comment above
1948// VG_(sigpending)() for more details.
1949#ifdef __amd64__
1950 I_die_here;
1951#else
sewardj73cf3bc2002-11-03 03:20:15 +00001952 Int res;
nethercotebf779682004-11-04 17:24:57 +00001953 UWord args[3];
sewardj73cf3bc2002-11-03 03:20:15 +00001954 args[0] = domain;
1955 args[1] = type;
1956 args[2] = protocol;
nethercotecf51cc42004-11-04 17:02:42 +00001957 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001958 if (VG_(is_kerror)(res))
1959 res = -1;
1960 return res;
njnc6168192004-11-29 13:54:10 +00001961#endif
sewardj73cf3bc2002-11-03 03:20:15 +00001962}
1963
1964static
1965Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
1966 Int addrlen )
1967{
njnc6168192004-11-29 13:54:10 +00001968// AMD64/Linux doesn't define __NR_socketcall... see comment above
1969// VG_(sigpending)() for more details.
1970#ifdef __amd64__
1971 I_die_here;
1972#else
sewardj73cf3bc2002-11-03 03:20:15 +00001973 Int res;
nethercotebf779682004-11-04 17:24:57 +00001974 UWord args[3];
sewardj73cf3bc2002-11-03 03:20:15 +00001975 args[0] = sockfd;
nethercotebf779682004-11-04 17:24:57 +00001976 args[1] = (UWord)serv_addr;
sewardj73cf3bc2002-11-03 03:20:15 +00001977 args[2] = addrlen;
nethercotecf51cc42004-11-04 17:02:42 +00001978 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00001979 if (VG_(is_kerror)(res))
1980 res = -1;
1981 return res;
njnc6168192004-11-29 13:54:10 +00001982#endif
sewardj73cf3bc2002-11-03 03:20:15 +00001983}
1984
1985Int VG_(write_socket)( Int sd, void *msg, Int count )
1986{
njnc6168192004-11-29 13:54:10 +00001987// AMD64/Linux doesn't define __NR_socketcall... see comment above
1988// VG_(sigpending)() for more details.
1989#ifdef __amd64__
1990 I_die_here;
1991#else
sewardj73cf3bc2002-11-03 03:20:15 +00001992 /* This is actually send(). */
sewardj570f8902002-11-03 11:44:36 +00001993
1994 /* Requests not to send SIGPIPE on errors on stream oriented
1995 sockets when the other end breaks the connection. The EPIPE
1996 error is still returned. */
nethercote73b526f2004-10-31 18:48:21 +00001997 Int flags = VKI_MSG_NOSIGNAL;
sewardj570f8902002-11-03 11:44:36 +00001998
sewardj73cf3bc2002-11-03 03:20:15 +00001999 Int res;
nethercotebf779682004-11-04 17:24:57 +00002000 UWord args[4];
sewardj73cf3bc2002-11-03 03:20:15 +00002001 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00002002 args[1] = (UWord)msg;
sewardj73cf3bc2002-11-03 03:20:15 +00002003 args[2] = count;
2004 args[3] = flags;
nethercotecf51cc42004-11-04 17:02:42 +00002005 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardj73cf3bc2002-11-03 03:20:15 +00002006 if (VG_(is_kerror)(res))
2007 res = -1;
2008 return res;
njnc6168192004-11-29 13:54:10 +00002009#endif
sewardj73cf3bc2002-11-03 03:20:15 +00002010}
2011
rjwalshf5f536f2003-11-17 17:45:00 +00002012Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
2013{
njnc6168192004-11-29 13:54:10 +00002014// AMD64/Linux doesn't define __NR_socketcall... see comment above
2015// VG_(sigpending)() for more details.
2016#ifdef __amd64__
2017 I_die_here;
2018#else
rjwalshf5f536f2003-11-17 17:45:00 +00002019 Int res;
nethercotebf779682004-11-04 17:24:57 +00002020 UWord args[3];
rjwalshf5f536f2003-11-17 17:45:00 +00002021 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00002022 args[1] = (UWord)name;
2023 args[2] = (UWord)namelen;
nethercotecf51cc42004-11-04 17:02:42 +00002024 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
rjwalshf5f536f2003-11-17 17:45:00 +00002025 if(VG_(is_kerror)(res))
2026 res = -1;
2027 return res;
njnc6168192004-11-29 13:54:10 +00002028#endif
rjwalshf5f536f2003-11-17 17:45:00 +00002029}
2030
2031Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
2032{
njnc6168192004-11-29 13:54:10 +00002033// AMD64/Linux doesn't define __NR_socketcall... see comment above
2034// VG_(sigpending)() for more details.
2035#ifdef __amd64__
2036 I_die_here;
2037#else
rjwalshf5f536f2003-11-17 17:45:00 +00002038 Int res;
nethercotebf779682004-11-04 17:24:57 +00002039 UWord args[3];
rjwalshf5f536f2003-11-17 17:45:00 +00002040 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00002041 args[1] = (UWord)name;
2042 args[2] = (UWord)namelen;
nethercotecf51cc42004-11-04 17:02:42 +00002043 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
rjwalshf5f536f2003-11-17 17:45:00 +00002044 if(VG_(is_kerror)(res))
2045 res = -1;
2046 return res;
njnc6168192004-11-29 13:54:10 +00002047#endif
rjwalshf5f536f2003-11-17 17:45:00 +00002048}
2049
2050Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
2051 Int *optlen)
2052{
njnc6168192004-11-29 13:54:10 +00002053// AMD64/Linux doesn't define __NR_socketcall... see comment above
2054// VG_(sigpending)() for more details.
2055#ifdef __amd64__
2056 I_die_here;
2057#else
rjwalshf5f536f2003-11-17 17:45:00 +00002058 Int res;
nethercotebf779682004-11-04 17:24:57 +00002059 UWord args[5];
rjwalshf5f536f2003-11-17 17:45:00 +00002060 args[0] = sd;
nethercotebf779682004-11-04 17:24:57 +00002061 args[1] = level;
2062 args[2] = optname;
2063 args[3] = (UWord)optval;
2064 args[4] = (UWord)optlen;
nethercotecf51cc42004-11-04 17:02:42 +00002065 res = VG_(do_syscall)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
rjwalshf5f536f2003-11-17 17:45:00 +00002066 if(VG_(is_kerror)(res))
2067 res = -1;
2068 return res;
njnc6168192004-11-29 13:54:10 +00002069#endif
rjwalshf5f536f2003-11-17 17:45:00 +00002070}
2071
sewardjde4a1d02002-03-22 01:27:54 +00002072/*--------------------------------------------------------------------*/
njnc6168192004-11-29 13:54:10 +00002073/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002074/*--------------------------------------------------------------------*/