blob: 1c5059c5ce064036d373cb7f1ae0c6d20df1ed30 [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
njn9f207462009-03-10 22:02:09 +000010 Copyright (C) 2003-2009 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"
40#include "valgrind.h"
41
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 { \
52 UChar ch = (UChar)((UInt)c); \
53 UChar* p = (UChar*)s; \
54 UChar* last = NULL; \
55 while (True) { \
56 if (*p == ch) last = p; \
57 if (*p == 0) return last; \
58 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 { \
78 UChar ch = (UChar)((UInt)c); \
79 UChar* p = (UChar*)s; \
80 while (True) { \
81 if (*p == ch) return p; \
82 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)
njne6154662009-02-10 04:23:41 +0000129STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
130STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
131STRLEN(VG_Z_LD_SO_1, strlen)
njnb4cfbc42009-05-04 04:20:02 +0000132#endif
sewardjdda0df82008-10-21 23:11:38 +0000133
134
sewardj024598e2008-09-18 14:43:05 +0000135#define STRCMP(soname, fnname) \
136 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
137 ( const char* s1, const char* s2 ); \
138 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
139 ( const char* s1, const char* s2 ) \
140 { \
141 register unsigned char c1; \
142 register unsigned char c2; \
143 while (True) { \
144 c1 = *(unsigned char *)s1; \
145 c2 = *(unsigned char *)s2; \
146 if (c1 != c2) break; \
147 if (c1 == 0) break; \
148 s1++; s2++; \
149 } \
150 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
151 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
152 return 0; \
153 }
154
njne6154662009-02-10 04:23:41 +0000155STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000156#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000157STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
158STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +0000159#endif
sewardj024598e2008-09-18 14:43:05 +0000160
161
sewardjda387f22010-02-15 09:57:49 +0000162#define MEMCHR(soname, fnname) \
163 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
164 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
165 { \
166 SizeT i; \
167 UChar c0 = (UChar)c; \
168 UChar* p = (UChar*)s; \
169 for (i = 0; i < n; i++) \
170 if (p[i] == c0) return (void*)(&p[i]); \
171 return NULL; \
172 }
173
174MEMCHR(VG_Z_LIBC_SONAME, memchr)
175#if defined(VGO_darwin)
176MEMCHR(VG_Z_DYLD, memchr)
177#endif
178
179
sewardj024598e2008-09-18 14:43:05 +0000180#define MEMCPY(soname, fnname) \
181 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
182 ( void *dst, const void *src, SizeT sz ); \
183 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
184 ( void *dest, const void *src, SizeT sz ) \
185 { \
186 const UChar* s = (const UChar*)src; \
187 UChar* d = (UChar*)dest; \
188 const UWord* sW = (const UWord*)src; \
189 UWord* dW = (UWord*)dest; \
190 const UWord al = sizeof(UWord)-1; \
191 \
192 if (0 == (((UWord)dW) & al) && 0 == (((UWord)sW) & al)) { \
193 while (sz >= 4 * sizeof(UWord)) { \
194 dW[0] = sW[0]; \
195 dW[1] = sW[1]; \
196 dW[2] = sW[2]; \
197 dW[3] = sW[3]; \
198 sz -= 4 * sizeof(UWord); \
199 dW += 4; \
200 sW += 4; \
201 } \
202 if (sz == 0) \
203 return dest; \
204 while (sz >= 1 * sizeof(UWord)) { \
205 dW[0] = sW[0]; \
206 sz -= 1 * sizeof(UWord); \
207 dW += 1; \
208 sW += 1; \
209 } \
210 if (sz == 0) \
211 return dest; \
212 s = (const UChar*)sW; \
213 d = (UChar*)dW; \
214 } \
215 \
216 while (sz--) \
217 *d++ = *s++; \
218 \
219 return dest; \
220 }
221
njne6154662009-02-10 04:23:41 +0000222MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +0000223#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000224MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
225MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnb4cfbc42009-05-04 04:20:02 +0000226#endif
sewardj024598e2008-09-18 14:43:05 +0000227
228
sewardjdda0df82008-10-21 23:11:38 +0000229/* Copy SRC to DEST, returning the address of the terminating '\0' in
230 DEST. (minor variant of strcpy) */
231#define STPCPY(soname, fnname) \
232 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
233 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
234 { \
235 while (*src) *dst++ = *src++; \
236 *dst = 0; \
237 \
238 return dst; \
239 }
240
njne6154662009-02-10 04:23:41 +0000241STPCPY(VG_Z_LIBC_SONAME, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000242#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +0000243STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
244STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
njnb4cfbc42009-05-04 04:20:02 +0000245#endif
sewardjdda0df82008-10-21 23:11:38 +0000246
247
sewardjda387f22010-02-15 09:57:49 +0000248/* Find the first occurrence of C in S. */
249#define GLIBC232_RAWMEMCHR(soname, fnname) \
250 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in); \
251 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const char* s, int c_in) \
252 { \
253 unsigned char c = (unsigned char) c_in; \
254 unsigned char* char_ptr = (unsigned char *)s; \
255 while (1) { \
256 if (*char_ptr == c) return char_ptr; \
257 char_ptr++; \
258 } \
259 }
260
261GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
262#if defined (VGO_linux)
263GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
264#endif
265
266
sewardj024598e2008-09-18 14:43:05 +0000267/*--------------------------------------------------------------------*/
268/*--- end pc_intercepts.c ---*/
269/*--------------------------------------------------------------------*/