• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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 
10    Copyright (C) 2003-2015 Nicholas Nethercote
11       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 "pub_tool_clreq.h"
41 
42 
43 /* The following intercepts are copied verbatim from
44    memcheck/mc_replace_strmem.c.  If you copy more in, please keep
45    them in the same order as in mc_replace_strmem.c. */
46 
47 
48 #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       HChar ch = (HChar)c;   \
53       const HChar* p = s;       \
54       const HChar* last = NULL; \
55       while (True) { \
56          if (*p == ch) last = p; \
57          if (*p == 0) return CONST_CAST(HChar *,last);    \
58          p++; \
59       } \
60    }
61 
62 // Apparently rindex() is the same thing as strrchr()
63 STRRCHR(VG_Z_LIBC_SONAME,   strrchr)
64 STRRCHR(VG_Z_LIBC_SONAME,   rindex)
65 #if defined(VGO_linux)
66 STRRCHR(VG_Z_LIBC_SONAME,   __GI_strrchr)
67 STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
68 #elif defined(VGO_darwin)
69 STRRCHR(VG_Z_DYLD,          strrchr)
70 STRRCHR(VG_Z_DYLD,          rindex)
71 #elif defined(VGO_solaris)
72 STRRCHR(VG_Z_LD_SO_1,       strrchr)
73 #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    { \
80       HChar  ch = (HChar)c ; \
81       const HChar* p  = s;   \
82       while (True) { \
83          if (*p == ch) return CONST_CAST(HChar *,p);       \
84          if (*p == 0) return NULL; \
85          p++; \
86       } \
87    }
88 
89 // Apparently index() is the same thing as strchr()
90 STRCHR(VG_Z_LIBC_SONAME,          strchr)
91 STRCHR(VG_Z_LIBC_SONAME,          index)
92 #if defined(VGO_linux)
93 STRCHR(VG_Z_LIBC_SONAME,          __GI_strchr)
94 STRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
95 STRCHR(VG_Z_LD_LINUX_SO_2,        index)
96 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
97 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
98 #elif defined(VGO_darwin)
99 STRCHR(VG_Z_DYLD,                 strchr)
100 STRCHR(VG_Z_DYLD,                 index)
101 #elif defined(VGO_solaris)
102 STRCHR(VG_Z_LD_SO_1,              strchr)
103 #endif
104 
105 
106 #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 
115 STRNLEN(VG_Z_LIBC_SONAME, strnlen)
116 
117 
118 // 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 
131 STRLEN(VG_Z_LIBC_SONAME,          strlen)
132 #if defined(VGO_linux)
133 STRLEN(VG_Z_LIBC_SONAME,          __GI_strlen)
134 STRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
135 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
136 STRLEN(VG_Z_LD_SO_1,              strlen)
137 #elif defined(VGO_solaris)
138 STRLEN(VG_Z_LD_SO_1,              strlen)
139 #endif
140 
141 
142 #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    { \
146       HChar* dst_orig = dst; \
147       \
148       while (*src) *dst++ = *src++; \
149       *dst = 0; \
150       \
151       return dst_orig; \
152    }
153 
154 STRCPY(VG_Z_LIBC_SONAME, strcpy)
155 #if defined(VGO_linux)
156 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
157 #elif defined(VGO_darwin)
158 STRCPY(VG_Z_DYLD,        strcpy)
159 #elif defined(VGO_solaris)
160 STRCPY(VG_Z_LD_SO_1,     strcpy)
161 #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          \
177          if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \
178          if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \
179          \
180          s1++; s2++; n++; \
181       } \
182    }
183 
184 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
185 #if defined(VGO_linux)
186 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
187 #elif defined(VGO_darwin)
188 STRNCMP(VG_Z_DYLD,        strncmp)
189 #endif
190 
191 
192 #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    { \
198       register UChar c1; \
199       register UChar c2; \
200       while (True) { \
201          c1 = *(const UChar *)s1; \
202          c2 = *(const UChar *)s2; \
203          if (c1 != c2) break; \
204          if (c1 == 0) break; \
205          s1++; s2++; \
206       } \
207       if ((UChar)c1 < (UChar)c2) return -1; \
208       if ((UChar)c1 > (UChar)c2) return 1; \
209       return 0; \
210    }
211 
212 STRCMP(VG_Z_LIBC_SONAME,          strcmp)
213 #if defined(VGO_linux)
214 STRCMP(VG_Z_LIBC_SONAME,          __GI_strcmp)
215 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
216 STRCMP(VG_Z_LD64_SO_1,            strcmp)
217 #elif defined(VGO_solaris)
218 STRCMP(VG_Z_LD_SO_1,              strcmp)
219 #endif
220 
221 
222 #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; \
228       const UChar* p = s; \
229       for (i = 0; i < n; i++) \
230          if (p[i] == c0) return CONST_CAST(void *,&p[i]);  \
231       return NULL; \
232    }
233 
234 MEMCHR(VG_Z_LIBC_SONAME, memchr)
235 #if defined(VGO_darwin)
236 MEMCHR(VG_Z_DYLD,        memchr)
237 #endif
238 
239 
240 #define MEMCPY(soname, fnname) \
241    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
242             ( void *dst, const void *src, SizeT len ); \
243    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
244             ( void *dst, const void *src, SizeT len ) \
245    { \
246       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          } \
305       } \
306       \
307       return dst; \
308    }
309 
310 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
311 #if defined(VGO_linux)
312 MEMCPY(VG_Z_LD_SO_1,     memcpy) /* ld.so.1 */
313 MEMCPY(VG_Z_LD64_SO_1,   memcpy) /* ld64.so.1 */
314 #elif defined(VGO_solaris)
315 MEMCPY(VG_Z_LD_SO_1,      memcpy)
316 #endif
317 
318 
319 /* 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 
331 STPCPY(VG_Z_LIBC_SONAME,          stpcpy)
332 #if defined(VGO_linux)
333 STPCPY(VG_Z_LD_LINUX_SO_2,        stpcpy)
334 STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
335 #endif
336 
337 
338 /* Find the first occurrence of C in S.  */
339 #define GLIBC232_RAWMEMCHR(soname, fnname) \
340    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) \
342    { \
343       UChar c = (UChar)c_in; \
344       const UChar* char_ptr = s; \
345       while (1) { \
346          if (*char_ptr == c) return CONST_CAST(void *,char_ptr);   \
347          char_ptr++; \
348       } \
349    }
350 
351 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
352 #if defined (VGO_linux)
353 GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
354 #endif
355 
356 
357 #define STRSTR(soname, fnname) \
358    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) \
362    { \
363       const HChar* h = haystack; \
364       const HChar* n = needle; \
365       \
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. */ \
371       if (nlen == 0) return CONST_CAST(HChar *,h);         \
372       \
373       /* assert(nlen >= 1); */ \
374       HChar n0 = n[0]; \
375       \
376       while (1) { \
377          const HChar hh = *h; \
378          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) \
388             return CONST_CAST(HChar *,h);          \
389          \
390          h++; \
391       } \
392    }
393 
394 #if defined(VGO_linux)
395 STRSTR(VG_Z_LIBC_SONAME,          strstr)
396 #elif defined(VGO_solaris)
397 STRSTR(VG_Z_LIBC_SONAME,          strstr)
398 #endif
399 
400 
401 #define STRPBRK(soname, fnname) \
402    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) \
406    { \
407       const HChar* s = sV; \
408       const HChar* accept = acceptV; \
409       \
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; \
420          HChar sc = *s; \
421          if (sc == 0) \
422             break; \
423          for (i = 0; i < nacc; i++) { \
424             if (sc == accept[i]) \
425                return CONST_CAST(HChar *,s);       \
426          } \
427          s++; \
428       } \
429       \
430       return NULL; \
431    }
432 
433 #if defined(VGO_linux)
434 STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
435 #elif defined(VGO_solaris)
436 STRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
437 #endif
438 
439 
440 /*--------------------------------------------------------------------*/
441 /*--- end                                          pc_intercepts.c ---*/
442 /*--------------------------------------------------------------------*/
443