blob: 81f846e75fb2795e2ffe898ba29d4259edc17cd5 [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
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2003-2017 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)
sewardj8eb8bab2015-07-21 14:44:28 +000071#elif defined(VGO_solaris)
72STRRCHR(VG_Z_LD_SO_1, strrchr)
sewardjda387f22010-02-15 09:57:49 +000073#endif
74
75
76#define STRCHR(soname, fnname) \
77 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
78 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
79 { \
florian654b5422012-11-18 00:36:15 +000080 HChar ch = (HChar)c ; \
81 const HChar* p = s; \
sewardjda387f22010-02-15 09:57:49 +000082 while (True) { \
florian70a5de12014-10-22 12:53:16 +000083 if (*p == ch) return CONST_CAST(HChar *,p); \
sewardjda387f22010-02-15 09:57:49 +000084 if (*p == 0) return NULL; \
85 p++; \
86 } \
87 }
88
89// Apparently index() is the same thing as strchr()
90STRCHR(VG_Z_LIBC_SONAME, strchr)
91STRCHR(VG_Z_LIBC_SONAME, index)
92#if defined(VGO_linux)
93STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
94STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
95STRCHR(VG_Z_LD_LINUX_SO_2, index)
96STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
97STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
98#elif defined(VGO_darwin)
99STRCHR(VG_Z_DYLD, strchr)
100STRCHR(VG_Z_DYLD, index)
sewardj8eb8bab2015-07-21 14:44:28 +0000101#elif defined(VGO_solaris)
102STRCHR(VG_Z_LD_SO_1, strchr)
sewardjda387f22010-02-15 09:57:49 +0000103#endif
104
105
sewardj7e98c032009-01-26 00:06:43 +0000106#define STRNLEN(soname, fnname) \
107 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
108 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
109 { \
110 SizeT i = 0; \
111 while (i < n && str[i] != 0) i++; \
112 return i; \
113 }
114
njne6154662009-02-10 04:23:41 +0000115STRNLEN(VG_Z_LIBC_SONAME, strnlen)
sewardj7e98c032009-01-26 00:06:43 +0000116
117
sewardjdda0df82008-10-21 23:11:38 +0000118// Note that this replacement often doesn't get used because gcc inlines
119// calls to strlen() with its own built-in version. This can be very
120// confusing if you aren't expecting it. Other small functions in this file
121// may also be inline by gcc.
122#define STRLEN(soname, fnname) \
123 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
124 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
125 { \
126 SizeT i = 0; \
127 while (str[i] != 0) i++; \
128 return i; \
129 }
130
njne6154662009-02-10 04:23:41 +0000131STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000132#if defined(VGO_linux)
sewardj4eff11b2010-08-16 22:56:16 +0000133STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
njne6154662009-02-10 04:23:41 +0000134STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
135STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
136STRLEN(VG_Z_LD_SO_1, strlen)
sewardj8eb8bab2015-07-21 14:44:28 +0000137#elif defined(VGO_solaris)
138STRLEN(VG_Z_LD_SO_1, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000139#endif
sewardjdda0df82008-10-21 23:11:38 +0000140
141
sewardj4eff11b2010-08-16 22:56:16 +0000142#define STRCPY(soname, fnname) \
143 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
144 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
145 { \
florian654b5422012-11-18 00:36:15 +0000146 HChar* dst_orig = dst; \
sewardj4eff11b2010-08-16 22:56:16 +0000147 \
148 while (*src) *dst++ = *src++; \
149 *dst = 0; \
150 \
151 return dst_orig; \
152 }
153
154STRCPY(VG_Z_LIBC_SONAME, strcpy)
155#if defined(VGO_linux)
156STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
157#elif defined(VGO_darwin)
158STRCPY(VG_Z_DYLD, strcpy)
sewardj8eb8bab2015-07-21 14:44:28 +0000159#elif defined(VGO_solaris)
160STRCPY(VG_Z_LD_SO_1, strcpy)
sewardj4eff11b2010-08-16 22:56:16 +0000161#endif
162
163
164#define STRNCMP(soname, fnname) \
165 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
166 ( const char* s1, const char* s2, SizeT nmax ); \
167 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
168 ( const char* s1, const char* s2, SizeT nmax ) \
169 { \
170 SizeT n = 0; \
171 while (True) { \
172 if (n >= nmax) return 0; \
173 if (*s1 == 0 && *s2 == 0) return 0; \
174 if (*s1 == 0) return -1; \
175 if (*s2 == 0) return 1; \
176 \
florian3e798632012-11-24 19:41:54 +0000177 if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \
178 if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \
sewardj4eff11b2010-08-16 22:56:16 +0000179 \
180 s1++; s2++; n++; \
181 } \
182 }
183
184STRNCMP(VG_Z_LIBC_SONAME, strncmp)
185#if defined(VGO_linux)
186STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
187#elif defined(VGO_darwin)
188STRNCMP(VG_Z_DYLD, strncmp)
189#endif
190
191
sewardj024598e2008-09-18 14:43:05 +0000192#define STRCMP(soname, fnname) \
193 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
194 ( const char* s1, const char* s2 ); \
195 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
196 ( const char* s1, const char* s2 ) \
197 { \
florian654b5422012-11-18 00:36:15 +0000198 register UChar c1; \
199 register UChar c2; \
sewardj024598e2008-09-18 14:43:05 +0000200 while (True) { \
florian3e798632012-11-24 19:41:54 +0000201 c1 = *(const UChar *)s1; \
202 c2 = *(const UChar *)s2; \
sewardj024598e2008-09-18 14:43:05 +0000203 if (c1 != c2) break; \
204 if (c1 == 0) break; \
205 s1++; s2++; \
206 } \
florian654b5422012-11-18 00:36:15 +0000207 if ((UChar)c1 < (UChar)c2) return -1; \
208 if ((UChar)c1 > (UChar)c2) return 1; \
sewardj024598e2008-09-18 14:43:05 +0000209 return 0; \
210 }
211
njne6154662009-02-10 04:23:41 +0000212STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000213#if defined(VGO_linux)
sewardj4eff11b2010-08-16 22:56:16 +0000214STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
njne6154662009-02-10 04:23:41 +0000215STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
216STRCMP(VG_Z_LD64_SO_1, strcmp)
sewardj8eb8bab2015-07-21 14:44:28 +0000217#elif defined(VGO_solaris)
218STRCMP(VG_Z_LD_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000219#endif
sewardj024598e2008-09-18 14:43:05 +0000220
221
sewardjda387f22010-02-15 09:57:49 +0000222#define MEMCHR(soname, fnname) \
223 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
224 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
225 { \
226 SizeT i; \
227 UChar c0 = (UChar)c; \
florian70a5de12014-10-22 12:53:16 +0000228 const UChar* p = s; \
sewardjda387f22010-02-15 09:57:49 +0000229 for (i = 0; i < n; i++) \
florian70a5de12014-10-22 12:53:16 +0000230 if (p[i] == c0) return CONST_CAST(void *,&p[i]); \
sewardjda387f22010-02-15 09:57:49 +0000231 return NULL; \
232 }
233
234MEMCHR(VG_Z_LIBC_SONAME, memchr)
235#if defined(VGO_darwin)
236MEMCHR(VG_Z_DYLD, memchr)
237#endif
238
239
sewardj024598e2008-09-18 14:43:05 +0000240#define MEMCPY(soname, fnname) \
241 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
sewardj650cf762012-08-24 16:42:57 +0000242 ( void *dst, const void *src, SizeT len ); \
sewardj024598e2008-09-18 14:43:05 +0000243 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
sewardj650cf762012-08-24 16:42:57 +0000244 ( void *dst, const void *src, SizeT len ) \
sewardj024598e2008-09-18 14:43:05 +0000245 { \
sewardj650cf762012-08-24 16:42:57 +0000246 const Addr WS = sizeof(UWord); /* 8 or 4 */ \
247 const Addr WM = WS - 1; /* 7 or 3 */ \
248 \
249 if (len > 0) { \
250 if (dst < src) { \
251 \
252 /* Copying backwards. */ \
253 SizeT n = len; \
254 Addr d = (Addr)dst; \
255 Addr s = (Addr)src; \
256 \
257 if (((s^d) & WM) == 0) { \
258 /* s and d have same UWord alignment. */ \
259 /* Pull up to a UWord boundary. */ \
260 while ((s & WM) != 0 && n >= 1) \
261 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
262 /* Copy UWords. */ \
263 while (n >= WS) \
264 { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
265 if (n == 0) \
266 return dst; \
267 } \
268 if (((s|d) & 1) == 0) { \
269 /* Both are 16-aligned; copy what we can thusly. */ \
270 while (n >= 2) \
271 { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
272 } \
273 /* Copy leftovers, or everything if misaligned. */ \
274 while (n >= 1) \
275 { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
276 \
277 } else if (dst > src) { \
278 \
279 SizeT n = len; \
280 Addr d = ((Addr)dst) + n; \
281 Addr s = ((Addr)src) + n; \
282 \
283 /* Copying forwards. */ \
284 if (((s^d) & WM) == 0) { \
285 /* s and d have same UWord alignment. */ \
286 /* Back down to a UWord boundary. */ \
287 while ((s & WM) != 0 && n >= 1) \
288 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
289 /* Copy UWords. */ \
290 while (n >= WS) \
291 { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
292 if (n == 0) \
293 return dst; \
294 } \
295 if (((s|d) & 1) == 0) { \
296 /* Both are 16-aligned; copy what we can thusly. */ \
297 while (n >= 2) \
298 { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
299 } \
300 /* Copy leftovers, or everything if misaligned. */ \
301 while (n >= 1) \
302 { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
303 \
304 } \
sewardj024598e2008-09-18 14:43:05 +0000305 } \
sewardj650cf762012-08-24 16:42:57 +0000306 \
307 return dst; \
sewardj024598e2008-09-18 14:43:05 +0000308 }
309
njne6154662009-02-10 04:23:41 +0000310MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000311#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000312MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
313MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
sewardj8eb8bab2015-07-21 14:44:28 +0000314#elif defined(VGO_solaris)
315MEMCPY(VG_Z_LD_SO_1, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000316#endif
sewardj024598e2008-09-18 14:43:05 +0000317
318
sewardjdda0df82008-10-21 23:11:38 +0000319/* Copy SRC to DEST, returning the address of the terminating '\0' in
320 DEST. (minor variant of strcpy) */
321#define STPCPY(soname, fnname) \
322 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
323 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
324 { \
325 while (*src) *dst++ = *src++; \
326 *dst = 0; \
327 \
328 return dst; \
329 }
330
njne6154662009-02-10 04:23:41 +0000331STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000332#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000333STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
334STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000335#endif
sewardjdda0df82008-10-21 23:11:38 +0000336
337
sewardjda387f22010-02-15 09:57:49 +0000338/* Find the first occurrence of C in S. */
339#define GLIBC232_RAWMEMCHR(soname, fnname) \
florian654b5422012-11-18 00:36:15 +0000340 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \
341 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \
sewardjda387f22010-02-15 09:57:49 +0000342 { \
florian654b5422012-11-18 00:36:15 +0000343 UChar c = (UChar)c_in; \
344 const UChar* char_ptr = s; \
sewardjda387f22010-02-15 09:57:49 +0000345 while (1) { \
florian70a5de12014-10-22 12:53:16 +0000346 if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \
sewardjda387f22010-02-15 09:57:49 +0000347 char_ptr++; \
348 } \
349 }
350
351GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
352#if defined (VGO_linux)
353GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
354#endif
355
356
sewardjadf9e4d2010-08-20 18:25:15 +0000357#define STRSTR(soname, fnname) \
florian654b5422012-11-18 00:36:15 +0000358 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
359 (const char* haystack, const char* needle); \
360 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
361 (const char* haystack, const char* needle) \
sewardjadf9e4d2010-08-20 18:25:15 +0000362 { \
florian654b5422012-11-18 00:36:15 +0000363 const HChar* h = haystack; \
364 const HChar* n = needle; \
sewardjadf9e4d2010-08-20 18:25:15 +0000365 \
366 /* find the length of n, not including terminating zero */ \
367 UWord nlen = 0; \
368 while (n[nlen]) nlen++; \
369 \
370 /* if n is the empty string, match immediately. */ \
florian70a5de12014-10-22 12:53:16 +0000371 if (nlen == 0) return CONST_CAST(HChar *,h); \
sewardjadf9e4d2010-08-20 18:25:15 +0000372 \
373 /* assert(nlen >= 1); */ \
florian654b5422012-11-18 00:36:15 +0000374 HChar n0 = n[0]; \
sewardjadf9e4d2010-08-20 18:25:15 +0000375 \
376 while (1) { \
florian654b5422012-11-18 00:36:15 +0000377 const HChar hh = *h; \
sewardjadf9e4d2010-08-20 18:25:15 +0000378 if (hh == 0) return NULL; \
379 if (hh != n0) { h++; continue; } \
380 \
381 UWord i; \
382 for (i = 0; i < nlen; i++) { \
383 if (n[i] != h[i]) \
384 break; \
385 } \
386 /* assert(i >= 0 && i <= nlen); */ \
387 if (i == nlen) \
florian70a5de12014-10-22 12:53:16 +0000388 return CONST_CAST(HChar *,h); \
sewardjadf9e4d2010-08-20 18:25:15 +0000389 \
390 h++; \
391 } \
392 }
393
394#if defined(VGO_linux)
395STRSTR(VG_Z_LIBC_SONAME, strstr)
sewardj8eb8bab2015-07-21 14:44:28 +0000396#elif defined(VGO_solaris)
397STRSTR(VG_Z_LIBC_SONAME, strstr)
sewardjadf9e4d2010-08-20 18:25:15 +0000398#endif
399
400
sewardj5446faa2010-08-21 09:04:38 +0000401#define STRPBRK(soname, fnname) \
florian654b5422012-11-18 00:36:15 +0000402 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
403 (const char* sV, const char* acceptV); \
404 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
405 (const char* sV, const char* acceptV) \
sewardj5446faa2010-08-21 09:04:38 +0000406 { \
florian654b5422012-11-18 00:36:15 +0000407 const HChar* s = sV; \
408 const HChar* accept = acceptV; \
sewardj5446faa2010-08-21 09:04:38 +0000409 \
410 /* find the length of 'accept', not including terminating zero */ \
411 UWord nacc = 0; \
412 while (accept[nacc]) nacc++; \
413 \
414 /* if n is the empty string, fail immediately. */ \
415 if (nacc == 0) return NULL; \
416 \
417 /* assert(nacc >= 1); */ \
418 while (1) { \
419 UWord i; \
florian654b5422012-11-18 00:36:15 +0000420 HChar sc = *s; \
sewardj5446faa2010-08-21 09:04:38 +0000421 if (sc == 0) \
422 break; \
423 for (i = 0; i < nacc; i++) { \
424 if (sc == accept[i]) \
florian70a5de12014-10-22 12:53:16 +0000425 return CONST_CAST(HChar *,s); \
sewardj5446faa2010-08-21 09:04:38 +0000426 } \
427 s++; \
428 } \
429 \
430 return NULL; \
431 }
432
433#if defined(VGO_linux)
434STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
sewardj8eb8bab2015-07-21 14:44:28 +0000435#elif defined(VGO_solaris)
436STRPBRK(VG_Z_LIBC_SONAME, strpbrk)
sewardj5446faa2010-08-21 09:04:38 +0000437#endif
438
439
sewardj024598e2008-09-18 14:43:05 +0000440/*--------------------------------------------------------------------*/
441/*--- end pc_intercepts.c ---*/
442/*--------------------------------------------------------------------*/