blob: 64bc7f7da2f2e3cd3b76da9bb90bd910f29b6865 [file] [log] [blame]
sewardj024598e2008-09-18 14:43:05 +00001
2/*--------------------------------------------------------------------*/
3/*--- Ptrcheck: a pointer-use checker. pc_intercepts.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Ptrcheck, a Valgrind tool for checking pointer
8 use in programs.
9
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2003-2013 Nicholas Nethercote
sewardj024598e2008-09-18 14:43:05 +000011 njn@valgrind.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31/* Nothing actually in here. However it appears this file is needed
32 to make malloc intercepting work. (jrs, 2 july 08 -- not sure about
33 that).
34*/
35
36#include "pub_tool_basics.h"
37#include "pub_tool_hashtable.h"
38#include "pub_tool_redir.h"
39#include "pub_tool_tooliface.h"
florian1a046d52013-09-16 20:56:35 +000040#include "pub_tool_clreq.h"
sewardj024598e2008-09-18 14:43:05 +000041
42
43/* The following intercepts are copied verbatim from
sewardjdda0df82008-10-21 23:11:38 +000044 memcheck/mc_replace_strmem.c. If you copy more in, please keep
45 them in the same order as in mc_replace_strmem.c. */
sewardj024598e2008-09-18 14:43:05 +000046
sewardj024598e2008-09-18 14:43:05 +000047
sewardjda387f22010-02-15 09:57:49 +000048#define STRRCHR(soname, fnname) \
49 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
50 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
51 { \
florian654b5422012-11-18 00:36:15 +000052 HChar ch = (HChar)c; \
53 const HChar* p = s; \
54 const HChar* last = NULL; \
sewardjda387f22010-02-15 09:57:49 +000055 while (True) { \
56 if (*p == ch) last = p; \
florian70a5de12014-10-22 12:53:16 +000057 if (*p == 0) return CONST_CAST(HChar *,last); \
sewardjda387f22010-02-15 09:57:49 +000058 p++; \
59 } \
60 }
61
62// Apparently rindex() is the same thing as strrchr()
63STRRCHR(VG_Z_LIBC_SONAME, strrchr)
64STRRCHR(VG_Z_LIBC_SONAME, rindex)
65#if defined(VGO_linux)
66STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
67STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
68#elif defined(VGO_darwin)
69STRRCHR(VG_Z_DYLD, strrchr)
70STRRCHR(VG_Z_DYLD, rindex)
71#endif
72
73
74#define STRCHR(soname, fnname) \
75 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
76 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
77 { \
florian654b5422012-11-18 00:36:15 +000078 HChar ch = (HChar)c ; \
79 const HChar* p = s; \
sewardjda387f22010-02-15 09:57:49 +000080 while (True) { \
florian70a5de12014-10-22 12:53:16 +000081 if (*p == ch) return CONST_CAST(HChar *,p); \
sewardjda387f22010-02-15 09:57:49 +000082 if (*p == 0) return NULL; \
83 p++; \
84 } \
85 }
86
87// Apparently index() is the same thing as strchr()
88STRCHR(VG_Z_LIBC_SONAME, strchr)
89STRCHR(VG_Z_LIBC_SONAME, index)
90#if defined(VGO_linux)
91STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
92STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
93STRCHR(VG_Z_LD_LINUX_SO_2, index)
94STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
95STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
96#elif defined(VGO_darwin)
97STRCHR(VG_Z_DYLD, strchr)
98STRCHR(VG_Z_DYLD, index)
99#endif
100
101
sewardj7e98c032009-01-26 00:06:43 +0000102#define STRNLEN(soname, fnname) \
103 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
104 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
105 { \
106 SizeT i = 0; \
107 while (i < n && str[i] != 0) i++; \
108 return i; \
109 }
110
njne6154662009-02-10 04:23:41 +0000111STRNLEN(VG_Z_LIBC_SONAME, strnlen)
sewardj7e98c032009-01-26 00:06:43 +0000112
113
sewardjdda0df82008-10-21 23:11:38 +0000114// Note that this replacement often doesn't get used because gcc inlines
115// calls to strlen() with its own built-in version. This can be very
116// confusing if you aren't expecting it. Other small functions in this file
117// may also be inline by gcc.
118#define STRLEN(soname, fnname) \
119 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
120 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
121 { \
122 SizeT i = 0; \
123 while (str[i] != 0) i++; \
124 return i; \
125 }
126
njne6154662009-02-10 04:23:41 +0000127STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000128#if defined(VGO_linux)
sewardj4eff11b2010-08-16 22:56:16 +0000129STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
njne6154662009-02-10 04:23:41 +0000130STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
131STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
132STRLEN(VG_Z_LD_SO_1, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000133#endif
sewardjdda0df82008-10-21 23:11:38 +0000134
135
sewardj4eff11b2010-08-16 22:56:16 +0000136#define STRCPY(soname, fnname) \
137 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
138 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
139 { \
florian654b5422012-11-18 00:36:15 +0000140 HChar* dst_orig = dst; \
sewardj4eff11b2010-08-16 22:56:16 +0000141 \
142 while (*src) *dst++ = *src++; \
143 *dst = 0; \
144 \
145 return dst_orig; \
146 }
147
148STRCPY(VG_Z_LIBC_SONAME, strcpy)
149#if defined(VGO_linux)
150STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
151#elif defined(VGO_darwin)
152STRCPY(VG_Z_DYLD, strcpy)
153#endif
154
155
156#define STRNCMP(soname, fnname) \
157 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
158 ( const char* s1, const char* s2, SizeT nmax ); \
159 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
160 ( const char* s1, const char* s2, SizeT nmax ) \
161 { \
162 SizeT n = 0; \
163 while (True) { \
164 if (n >= nmax) return 0; \
165 if (*s1 == 0 && *s2 == 0) return 0; \
166 if (*s1 == 0) return -1; \
167 if (*s2 == 0) return 1; \
168 \
florian3e798632012-11-24 19:41:54 +0000169 if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \
170 if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \
sewardj4eff11b2010-08-16 22:56:16 +0000171 \
172 s1++; s2++; n++; \
173 } \
174 }
175
176STRNCMP(VG_Z_LIBC_SONAME, strncmp)
177#if defined(VGO_linux)
178STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
179#elif defined(VGO_darwin)
180STRNCMP(VG_Z_DYLD, strncmp)
181#endif
182
183
sewardj024598e2008-09-18 14:43:05 +0000184#define STRCMP(soname, fnname) \
185 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
186 ( const char* s1, const char* s2 ); \
187 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
188 ( const char* s1, const char* s2 ) \
189 { \
florian654b5422012-11-18 00:36:15 +0000190 register UChar c1; \
191 register UChar c2; \
sewardj024598e2008-09-18 14:43:05 +0000192 while (True) { \
florian3e798632012-11-24 19:41:54 +0000193 c1 = *(const UChar *)s1; \
194 c2 = *(const UChar *)s2; \
sewardj024598e2008-09-18 14:43:05 +0000195 if (c1 != c2) break; \
196 if (c1 == 0) break; \
197 s1++; s2++; \
198 } \
florian654b5422012-11-18 00:36:15 +0000199 if ((UChar)c1 < (UChar)c2) return -1; \
200 if ((UChar)c1 > (UChar)c2) return 1; \
sewardj024598e2008-09-18 14:43:05 +0000201 return 0; \
202 }
203
njne6154662009-02-10 04:23:41 +0000204STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000205#if defined(VGO_linux)
sewardj4eff11b2010-08-16 22:56:16 +0000206STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
njne6154662009-02-10 04:23:41 +0000207STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
208STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000209#endif
sewardj024598e2008-09-18 14:43:05 +0000210
211
sewardjda387f22010-02-15 09:57:49 +0000212#define MEMCHR(soname, fnname) \
213 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
214 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
215 { \
216 SizeT i; \
217 UChar c0 = (UChar)c; \
florian70a5de12014-10-22 12:53:16 +0000218 const UChar* p = s; \
sewardjda387f22010-02-15 09:57:49 +0000219 for (i = 0; i < n; i++) \
florian70a5de12014-10-22 12:53:16 +0000220 if (p[i] == c0) return CONST_CAST(void *,&p[i]); \
sewardjda387f22010-02-15 09:57:49 +0000221 return NULL; \
222 }
223
224MEMCHR(VG_Z_LIBC_SONAME, memchr)
225#if defined(VGO_darwin)
226MEMCHR(VG_Z_DYLD, memchr)
227#endif
228
229
sewardj024598e2008-09-18 14:43:05 +0000230#define MEMCPY(soname, fnname) \
231 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
sewardj650cf762012-08-24 16:42:57 +0000232 ( void *dst, const void *src, SizeT len ); \
sewardj024598e2008-09-18 14:43:05 +0000233 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
sewardj650cf762012-08-24 16:42:57 +0000234 ( void *dst, const void *src, SizeT len ) \
sewardj024598e2008-09-18 14:43:05 +0000235 { \
sewardj650cf762012-08-24 16:42:57 +0000236 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
237 const Addr WM = WS - 1; /* 7 or 3 */ \
238 \
239 if (len > 0) { \
240 if (dst < src) { \
241 \
242 /* Copying backwards. */ \
243 SizeT n = len; \
244 Addr d = (Addr)dst; \
245 Addr s = (Addr)src; \
246 \
247 if (((s^d) & WM) == 0) { \
248 /* s and d have same UWord alignment. */ \
249 /* Pull up to a UWord boundary. */ \
250 while ((s & WM) != 0 && n >= 1) \
251 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
252 /* Copy UWords. */ \
253 while (n >= WS) \
254 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
255 if (n == 0) \
256 return dst; \
257 } \
258 if (((s|d) & 1) == 0) { \
259 /* Both are 16-aligned; copy what we can thusly. */ \
260 while (n >= 2) \
261 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
262 } \
263 /* Copy leftovers, or everything if misaligned. */ \
264 while (n >= 1) \
265 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
266 \
267 } else if (dst > src) { \
268 \
269 SizeT n = len; \
270 Addr d = ((Addr)dst) + n; \
271 Addr s = ((Addr)src) + n; \
272 \
273 /* Copying forwards. */ \
274 if (((s^d) & WM) == 0) { \
275 /* s and d have same UWord alignment. */ \
276 /* Back down to a UWord boundary. */ \
277 while ((s & WM) != 0 && n >= 1) \
278 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
279 /* Copy UWords. */ \
280 while (n >= WS) \
281 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
282 if (n == 0) \
283 return dst; \
284 } \
285 if (((s|d) & 1) == 0) { \
286 /* Both are 16-aligned; copy what we can thusly. */ \
287 while (n >= 2) \
288 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
289 } \
290 /* Copy leftovers, or everything if misaligned. */ \
291 while (n >= 1) \
292 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
293 \
294 } \
sewardj024598e2008-09-18 14:43:05 +0000295 } \
sewardj650cf762012-08-24 16:42:57 +0000296 \
297 return dst; \
sewardj024598e2008-09-18 14:43:05 +0000298 }
299
njne6154662009-02-10 04:23:41 +0000300MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000301#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000302MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
303MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnb4cfbc42009-05-04 04:20:02 +0000304#endif
sewardj024598e2008-09-18 14:43:05 +0000305
306
sewardjdda0df82008-10-21 23:11:38 +0000307/* Copy SRC to DEST, returning the address of the terminating '\0' in
308 DEST. (minor variant of strcpy) */
309#define STPCPY(soname, fnname) \
310 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
311 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
312 { \
313 while (*src) *dst++ = *src++; \
314 *dst = 0; \
315 \
316 return dst; \
317 }
318
njne6154662009-02-10 04:23:41 +0000319STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000320#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000321STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
322STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000323#endif
sewardjdda0df82008-10-21 23:11:38 +0000324
325
sewardjda387f22010-02-15 09:57:49 +0000326/* Find the first occurrence of C in S. */
327#define GLIBC232_RAWMEMCHR(soname, fnname) \
florian654b5422012-11-18 00:36:15 +0000328 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \
329 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \
sewardjda387f22010-02-15 09:57:49 +0000330 { \
florian654b5422012-11-18 00:36:15 +0000331 UChar c = (UChar)c_in; \
332 const UChar* char_ptr = s; \
sewardjda387f22010-02-15 09:57:49 +0000333 while (1) { \
florian70a5de12014-10-22 12:53:16 +0000334 if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \
sewardjda387f22010-02-15 09:57:49 +0000335 char_ptr++; \
336 } \
337 }
338
339GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
340#if defined (VGO_linux)
341GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
342#endif
343
344
sewardjadf9e4d2010-08-20 18:25:15 +0000345#define STRSTR(soname, fnname) \
florian654b5422012-11-18 00:36:15 +0000346 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
347 (const char* haystack, const char* needle); \
348 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
349 (const char* haystack, const char* needle) \
sewardjadf9e4d2010-08-20 18:25:15 +0000350 { \
florian654b5422012-11-18 00:36:15 +0000351 const HChar* h = haystack; \
352 const HChar* n = needle; \
sewardjadf9e4d2010-08-20 18:25:15 +0000353 \
354 /* find the length of n, not including terminating zero */ \
355 UWord nlen = 0; \
356 while (n[nlen]) nlen++; \
357 \
358 /* if n is the empty string, match immediately. */ \
florian70a5de12014-10-22 12:53:16 +0000359 if (nlen == 0) return CONST_CAST(HChar *,h); \
sewardjadf9e4d2010-08-20 18:25:15 +0000360 \
361 /* assert(nlen >= 1); */ \
florian654b5422012-11-18 00:36:15 +0000362 HChar n0 = n[0]; \
sewardjadf9e4d2010-08-20 18:25:15 +0000363 \
364 while (1) { \
florian654b5422012-11-18 00:36:15 +0000365 const HChar hh = *h; \
sewardjadf9e4d2010-08-20 18:25:15 +0000366 if (hh == 0) return NULL; \
367 if (hh != n0) { h++; continue; } \
368 \
369 UWord i; \
370 for (i = 0; i < nlen; i++) { \
371 if (n[i] != h[i]) \
372 break; \
373 } \
374 /* assert(i >= 0 && i <= nlen); */ \
375 if (i == nlen) \
florian70a5de12014-10-22 12:53:16 +0000376 return CONST_CAST(HChar *,h); \
sewardjadf9e4d2010-08-20 18:25:15 +0000377 \
378 h++; \
379 } \
380 }
381
382#if defined(VGO_linux)
383STRSTR(VG_Z_LIBC_SONAME, strstr)
384#endif
385
386
sewardj5446faa2010-08-21 09:04:38 +0000387#define STRPBRK(soname, fnname) \
florian654b5422012-11-18 00:36:15 +0000388 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
389 (const char* sV, const char* acceptV); \
390 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
391 (const char* sV, const char* acceptV) \
sewardj5446faa2010-08-21 09:04:38 +0000392 { \
florian654b5422012-11-18 00:36:15 +0000393 const HChar* s = sV; \
394 const HChar* accept = acceptV; \
sewardj5446faa2010-08-21 09:04:38 +0000395 \
396 /* find the length of 'accept', not including terminating zero */ \
397 UWord nacc = 0; \
398 while (accept[nacc]) nacc++; \
399 \
400 /* if n is the empty string, fail immediately. */ \
401 if (nacc == 0) return NULL; \
402 \
403 /* assert(nacc >= 1); */ \
404 while (1) { \
405 UWord i; \
florian654b5422012-11-18 00:36:15 +0000406 HChar sc = *s; \
sewardj5446faa2010-08-21 09:04:38 +0000407 if (sc == 0) \
408 break; \
409 for (i = 0; i < nacc; i++) { \
410 if (sc == accept[i]) \
florian70a5de12014-10-22 12:53:16 +0000411 return CONST_CAST(HChar *,s); \
sewardj5446faa2010-08-21 09:04:38 +0000412 } \
413 s++; \
414 } \
415 \
416 return NULL; \
417 }
418
419#if defined(VGO_linux)
420STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
421#endif
422
423
sewardj024598e2008-09-18 14:43:05 +0000424/*--------------------------------------------------------------------*/
425/*--- end pc_intercepts.c ---*/
426/*--------------------------------------------------------------------*/