1024598e40c84666cc311a42c256bbf880db3ac99sewardj
2024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
3024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Ptrcheck: a pointer-use checker.             pc_intercepts.c ---*/
4024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
5024598e40c84666cc311a42c256bbf880db3ac99sewardj
6024598e40c84666cc311a42c256bbf880db3ac99sewardj/*
7024598e40c84666cc311a42c256bbf880db3ac99sewardj   This file is part of Ptrcheck, a Valgrind tool for checking pointer
8024598e40c84666cc311a42c256bbf880db3ac99sewardj   use in programs.
9024598e40c84666cc311a42c256bbf880db3ac99sewardj
100f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2003-2013 Nicholas Nethercote
11024598e40c84666cc311a42c256bbf880db3ac99sewardj      njn@valgrind.org
12024598e40c84666cc311a42c256bbf880db3ac99sewardj
13024598e40c84666cc311a42c256bbf880db3ac99sewardj   This program is free software; you can redistribute it and/or
14024598e40c84666cc311a42c256bbf880db3ac99sewardj   modify it under the terms of the GNU General Public License as
15024598e40c84666cc311a42c256bbf880db3ac99sewardj   published by the Free Software Foundation; either version 2 of the
16024598e40c84666cc311a42c256bbf880db3ac99sewardj   License, or (at your option) any later version.
17024598e40c84666cc311a42c256bbf880db3ac99sewardj
18024598e40c84666cc311a42c256bbf880db3ac99sewardj   This program is distributed in the hope that it will be useful, but
19024598e40c84666cc311a42c256bbf880db3ac99sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20024598e40c84666cc311a42c256bbf880db3ac99sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21024598e40c84666cc311a42c256bbf880db3ac99sewardj   General Public License for more details.
22024598e40c84666cc311a42c256bbf880db3ac99sewardj
23024598e40c84666cc311a42c256bbf880db3ac99sewardj   You should have received a copy of the GNU General Public License
24024598e40c84666cc311a42c256bbf880db3ac99sewardj   along with this program; if not, write to the Free Software
25024598e40c84666cc311a42c256bbf880db3ac99sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26024598e40c84666cc311a42c256bbf880db3ac99sewardj   02111-1307, USA.
27024598e40c84666cc311a42c256bbf880db3ac99sewardj
28024598e40c84666cc311a42c256bbf880db3ac99sewardj   The GNU General Public License is contained in the file COPYING.
29024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
30024598e40c84666cc311a42c256bbf880db3ac99sewardj
31024598e40c84666cc311a42c256bbf880db3ac99sewardj/* Nothing actually in here.  However it appears this file is needed
32024598e40c84666cc311a42c256bbf880db3ac99sewardj   to make malloc intercepting work. (jrs, 2 july 08 -- not sure about
33024598e40c84666cc311a42c256bbf880db3ac99sewardj   that).
34024598e40c84666cc311a42c256bbf880db3ac99sewardj*/
35024598e40c84666cc311a42c256bbf880db3ac99sewardj
36024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_basics.h"
37024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_hashtable.h"
38024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_redir.h"
39024598e40c84666cc311a42c256bbf880db3ac99sewardj#include "pub_tool_tooliface.h"
401a046d5a3c34f924b648cc22c01f0a8e02ca221eflorian#include "pub_tool_clreq.h"
41024598e40c84666cc311a42c256bbf880db3ac99sewardj
42024598e40c84666cc311a42c256bbf880db3ac99sewardj
43024598e40c84666cc311a42c256bbf880db3ac99sewardj/* The following intercepts are copied verbatim from
44dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   memcheck/mc_replace_strmem.c.  If you copy more in, please keep
45dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   them in the same order as in mc_replace_strmem.c. */
46024598e40c84666cc311a42c256bbf880db3ac99sewardj
47024598e40c84666cc311a42c256bbf880db3ac99sewardj
48da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#define STRRCHR(soname, fnname) \
49da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \
50da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \
51da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   { \
52654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      HChar ch = (HChar)c;   \
53654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* p = s;       \
54654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* last = NULL; \
55da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      while (True) { \
56da387f2a63296760a87ce4b929fe7f95c52567bbsewardj         if (*p == ch) last = p; \
5770a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian         if (*p == 0) return CONST_CAST(HChar *,last);    \
58da387f2a63296760a87ce4b929fe7f95c52567bbsewardj         p++; \
59da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      } \
60da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   }
61da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
62da387f2a63296760a87ce4b929fe7f95c52567bbsewardj// Apparently rindex() is the same thing as strrchr()
63da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRRCHR(VG_Z_LIBC_SONAME,   strrchr)
64da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRRCHR(VG_Z_LIBC_SONAME,   rindex)
65da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#if defined(VGO_linux)
66da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRRCHR(VG_Z_LIBC_SONAME,   __GI_strrchr)
67da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
68da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#elif defined(VGO_darwin)
69da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRRCHR(VG_Z_DYLD,          strrchr)
70da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRRCHR(VG_Z_DYLD,          rindex)
71da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#endif
72da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
73da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
74da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#define STRCHR(soname, fnname) \
75da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
76da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
77da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   { \
78654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      HChar  ch = (HChar)c ; \
79654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* p  = s;   \
80da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      while (True) { \
8170a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian         if (*p == ch) return CONST_CAST(HChar *,p);       \
82da387f2a63296760a87ce4b929fe7f95c52567bbsewardj         if (*p == 0) return NULL; \
83da387f2a63296760a87ce4b929fe7f95c52567bbsewardj         p++; \
84da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      } \
85da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   }
86da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
87da387f2a63296760a87ce4b929fe7f95c52567bbsewardj// Apparently index() is the same thing as strchr()
88da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LIBC_SONAME,          strchr)
89da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LIBC_SONAME,          index)
90da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#if defined(VGO_linux)
91da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LIBC_SONAME,          __GI_strchr)
92da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
93da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LD_LINUX_SO_2,        index)
94da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
95da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
96da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#elif defined(VGO_darwin)
97da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_DYLD,                 strchr)
98da387f2a63296760a87ce4b929fe7f95c52567bbsewardjSTRCHR(VG_Z_DYLD,                 index)
99da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#endif
100da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
101da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
1027e98c03c14ced31df09fa665ba3151ef9e551272sewardj#define STRNLEN(soname, fnname) \
1037e98c03c14ced31df09fa665ba3151ef9e551272sewardj   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \
1047e98c03c14ced31df09fa665ba3151ef9e551272sewardj   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \
1057e98c03c14ced31df09fa665ba3151ef9e551272sewardj   { \
1067e98c03c14ced31df09fa665ba3151ef9e551272sewardj      SizeT i = 0; \
1077e98c03c14ced31df09fa665ba3151ef9e551272sewardj      while (i < n && str[i] != 0) i++; \
1087e98c03c14ced31df09fa665ba3151ef9e551272sewardj      return i; \
1097e98c03c14ced31df09fa665ba3151ef9e551272sewardj   }
1107e98c03c14ced31df09fa665ba3151ef9e551272sewardj
111e61546621e9bca129420399d7c552f8f63c93509njnSTRNLEN(VG_Z_LIBC_SONAME, strnlen)
1127e98c03c14ced31df09fa665ba3151ef9e551272sewardj
1137e98c03c14ced31df09fa665ba3151ef9e551272sewardj
114dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj// Note that this replacement often doesn't get used because gcc inlines
115dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj// calls to strlen() with its own built-in version.  This can be very
116dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj// confusing if you aren't expecting it.  Other small functions in this file
117dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj// may also be inline by gcc.
118dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj#define STRLEN(soname, fnname) \
119dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
120dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
121dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   { \
122dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      SizeT i = 0; \
123dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      while (str[i] != 0) i++; \
124dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      return i; \
125dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   }
126dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj
127e61546621e9bca129420399d7c552f8f63c93509njnSTRLEN(VG_Z_LIBC_SONAME,          strlen)
128b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#if defined(VGO_linux)
1294eff11b28c8884c2936deea57fb308df289af473sewardjSTRLEN(VG_Z_LIBC_SONAME,          __GI_strlen)
130e61546621e9bca129420399d7c552f8f63c93509njnSTRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
131e61546621e9bca129420399d7c552f8f63c93509njnSTRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
132e61546621e9bca129420399d7c552f8f63c93509njnSTRLEN(VG_Z_LD_SO_1,              strlen)
133b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#endif
134dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj
135dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj
1364eff11b28c8884c2936deea57fb308df289af473sewardj#define STRCPY(soname, fnname) \
1374eff11b28c8884c2936deea57fb308df289af473sewardj   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
1384eff11b28c8884c2936deea57fb308df289af473sewardj   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
1394eff11b28c8884c2936deea57fb308df289af473sewardj   { \
140654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      HChar* dst_orig = dst; \
1414eff11b28c8884c2936deea57fb308df289af473sewardj      \
1424eff11b28c8884c2936deea57fb308df289af473sewardj      while (*src) *dst++ = *src++; \
1434eff11b28c8884c2936deea57fb308df289af473sewardj      *dst = 0; \
1444eff11b28c8884c2936deea57fb308df289af473sewardj      \
1454eff11b28c8884c2936deea57fb308df289af473sewardj      return dst_orig; \
1464eff11b28c8884c2936deea57fb308df289af473sewardj   }
1474eff11b28c8884c2936deea57fb308df289af473sewardj
1484eff11b28c8884c2936deea57fb308df289af473sewardjSTRCPY(VG_Z_LIBC_SONAME, strcpy)
1494eff11b28c8884c2936deea57fb308df289af473sewardj#if defined(VGO_linux)
1504eff11b28c8884c2936deea57fb308df289af473sewardjSTRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
1514eff11b28c8884c2936deea57fb308df289af473sewardj#elif defined(VGO_darwin)
1524eff11b28c8884c2936deea57fb308df289af473sewardjSTRCPY(VG_Z_DYLD,        strcpy)
1534eff11b28c8884c2936deea57fb308df289af473sewardj#endif
1544eff11b28c8884c2936deea57fb308df289af473sewardj
1554eff11b28c8884c2936deea57fb308df289af473sewardj
1564eff11b28c8884c2936deea57fb308df289af473sewardj#define STRNCMP(soname, fnname) \
1574eff11b28c8884c2936deea57fb308df289af473sewardj   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1584eff11b28c8884c2936deea57fb308df289af473sewardj          ( const char* s1, const char* s2, SizeT nmax ); \
1594eff11b28c8884c2936deea57fb308df289af473sewardj   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
1604eff11b28c8884c2936deea57fb308df289af473sewardj          ( const char* s1, const char* s2, SizeT nmax ) \
1614eff11b28c8884c2936deea57fb308df289af473sewardj   { \
1624eff11b28c8884c2936deea57fb308df289af473sewardj      SizeT n = 0; \
1634eff11b28c8884c2936deea57fb308df289af473sewardj      while (True) { \
1644eff11b28c8884c2936deea57fb308df289af473sewardj         if (n >= nmax) return 0; \
1654eff11b28c8884c2936deea57fb308df289af473sewardj         if (*s1 == 0 && *s2 == 0) return 0; \
1664eff11b28c8884c2936deea57fb308df289af473sewardj         if (*s1 == 0) return -1; \
1674eff11b28c8884c2936deea57fb308df289af473sewardj         if (*s2 == 0) return 1; \
1684eff11b28c8884c2936deea57fb308df289af473sewardj         \
1693e7986312a0ffc7646b0552d4c4ea3744a870e73florian         if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \
1703e7986312a0ffc7646b0552d4c4ea3744a870e73florian         if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \
1714eff11b28c8884c2936deea57fb308df289af473sewardj         \
1724eff11b28c8884c2936deea57fb308df289af473sewardj         s1++; s2++; n++; \
1734eff11b28c8884c2936deea57fb308df289af473sewardj      } \
1744eff11b28c8884c2936deea57fb308df289af473sewardj   }
1754eff11b28c8884c2936deea57fb308df289af473sewardj
1764eff11b28c8884c2936deea57fb308df289af473sewardjSTRNCMP(VG_Z_LIBC_SONAME, strncmp)
1774eff11b28c8884c2936deea57fb308df289af473sewardj#if defined(VGO_linux)
1784eff11b28c8884c2936deea57fb308df289af473sewardjSTRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
1794eff11b28c8884c2936deea57fb308df289af473sewardj#elif defined(VGO_darwin)
1804eff11b28c8884c2936deea57fb308df289af473sewardjSTRNCMP(VG_Z_DYLD,        strncmp)
1814eff11b28c8884c2936deea57fb308df289af473sewardj#endif
1824eff11b28c8884c2936deea57fb308df289af473sewardj
1834eff11b28c8884c2936deea57fb308df289af473sewardj
184024598e40c84666cc311a42c256bbf880db3ac99sewardj#define STRCMP(soname, fnname) \
185024598e40c84666cc311a42c256bbf880db3ac99sewardj   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
186024598e40c84666cc311a42c256bbf880db3ac99sewardj          ( const char* s1, const char* s2 ); \
187024598e40c84666cc311a42c256bbf880db3ac99sewardj   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
188024598e40c84666cc311a42c256bbf880db3ac99sewardj          ( const char* s1, const char* s2 ) \
189024598e40c84666cc311a42c256bbf880db3ac99sewardj   { \
190654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      register UChar c1; \
191654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      register UChar c2; \
192024598e40c84666cc311a42c256bbf880db3ac99sewardj      while (True) { \
1933e7986312a0ffc7646b0552d4c4ea3744a870e73florian         c1 = *(const UChar *)s1; \
1943e7986312a0ffc7646b0552d4c4ea3744a870e73florian         c2 = *(const UChar *)s2; \
195024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (c1 != c2) break; \
196024598e40c84666cc311a42c256bbf880db3ac99sewardj         if (c1 == 0) break; \
197024598e40c84666cc311a42c256bbf880db3ac99sewardj         s1++; s2++; \
198024598e40c84666cc311a42c256bbf880db3ac99sewardj      } \
199654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      if ((UChar)c1 < (UChar)c2) return -1; \
200654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      if ((UChar)c1 > (UChar)c2) return 1; \
201024598e40c84666cc311a42c256bbf880db3ac99sewardj      return 0; \
202024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
203024598e40c84666cc311a42c256bbf880db3ac99sewardj
204e61546621e9bca129420399d7c552f8f63c93509njnSTRCMP(VG_Z_LIBC_SONAME,          strcmp)
205b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#if defined(VGO_linux)
2064eff11b28c8884c2936deea57fb308df289af473sewardjSTRCMP(VG_Z_LIBC_SONAME,          __GI_strcmp)
207e61546621e9bca129420399d7c552f8f63c93509njnSTRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
208e61546621e9bca129420399d7c552f8f63c93509njnSTRCMP(VG_Z_LD64_SO_1,            strcmp)
209b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#endif
210024598e40c84666cc311a42c256bbf880db3ac99sewardj
211024598e40c84666cc311a42c256bbf880db3ac99sewardj
212da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#define MEMCHR(soname, fnname) \
213da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
214da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
215da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   { \
216da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      SizeT i; \
217da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      UChar c0 = (UChar)c; \
21870a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian      const UChar* p = s; \
219da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      for (i = 0; i < n; i++) \
22070a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian         if (p[i] == c0) return CONST_CAST(void *,&p[i]);  \
221da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      return NULL; \
222da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   }
223da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
224da387f2a63296760a87ce4b929fe7f95c52567bbsewardjMEMCHR(VG_Z_LIBC_SONAME, memchr)
225da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#if defined(VGO_darwin)
226da387f2a63296760a87ce4b929fe7f95c52567bbsewardjMEMCHR(VG_Z_DYLD,        memchr)
227da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#endif
228da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
229da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
230024598e40c84666cc311a42c256bbf880db3ac99sewardj#define MEMCPY(soname, fnname) \
231024598e40c84666cc311a42c256bbf880db3ac99sewardj   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
232650cf7698fdd0807a49588376cfefae5289e4488sewardj            ( void *dst, const void *src, SizeT len ); \
233024598e40c84666cc311a42c256bbf880db3ac99sewardj   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
234650cf7698fdd0807a49588376cfefae5289e4488sewardj            ( void *dst, const void *src, SizeT len ) \
235024598e40c84666cc311a42c256bbf880db3ac99sewardj   { \
236650cf7698fdd0807a49588376cfefae5289e4488sewardj      const Addr WS = sizeof(UWord); /* 8 or 4 */ \
237650cf7698fdd0807a49588376cfefae5289e4488sewardj      const Addr WM = WS - 1;        /* 7 or 3 */ \
238650cf7698fdd0807a49588376cfefae5289e4488sewardj      \
239650cf7698fdd0807a49588376cfefae5289e4488sewardj      if (len > 0) { \
240650cf7698fdd0807a49588376cfefae5289e4488sewardj         if (dst < src) { \
241650cf7698fdd0807a49588376cfefae5289e4488sewardj         \
242650cf7698fdd0807a49588376cfefae5289e4488sewardj            /* Copying backwards. */ \
243650cf7698fdd0807a49588376cfefae5289e4488sewardj            SizeT n = len; \
244650cf7698fdd0807a49588376cfefae5289e4488sewardj            Addr  d = (Addr)dst; \
245650cf7698fdd0807a49588376cfefae5289e4488sewardj            Addr  s = (Addr)src; \
246650cf7698fdd0807a49588376cfefae5289e4488sewardj            \
247650cf7698fdd0807a49588376cfefae5289e4488sewardj            if (((s^d) & WM) == 0) { \
248650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* s and d have same UWord alignment. */ \
249650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* Pull up to a UWord boundary. */ \
250650cf7698fdd0807a49588376cfefae5289e4488sewardj               while ((s & WM) != 0 && n >= 1) \
251650cf7698fdd0807a49588376cfefae5289e4488sewardj                  { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
252650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* Copy UWords. */ \
253650cf7698fdd0807a49588376cfefae5289e4488sewardj               while (n >= WS) \
254650cf7698fdd0807a49588376cfefae5289e4488sewardj                  { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \
255650cf7698fdd0807a49588376cfefae5289e4488sewardj               if (n == 0) \
256650cf7698fdd0807a49588376cfefae5289e4488sewardj                  return dst; \
257650cf7698fdd0807a49588376cfefae5289e4488sewardj            } \
258650cf7698fdd0807a49588376cfefae5289e4488sewardj            if (((s|d) & 1) == 0) { \
259650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* Both are 16-aligned; copy what we can thusly. */ \
260650cf7698fdd0807a49588376cfefae5289e4488sewardj               while (n >= 2) \
261650cf7698fdd0807a49588376cfefae5289e4488sewardj                  { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \
262650cf7698fdd0807a49588376cfefae5289e4488sewardj            } \
263650cf7698fdd0807a49588376cfefae5289e4488sewardj            /* Copy leftovers, or everything if misaligned. */ \
264650cf7698fdd0807a49588376cfefae5289e4488sewardj            while (n >= 1) \
265650cf7698fdd0807a49588376cfefae5289e4488sewardj               { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \
266650cf7698fdd0807a49588376cfefae5289e4488sewardj         \
267650cf7698fdd0807a49588376cfefae5289e4488sewardj         } else if (dst > src) { \
268650cf7698fdd0807a49588376cfefae5289e4488sewardj         \
269650cf7698fdd0807a49588376cfefae5289e4488sewardj            SizeT n = len; \
270650cf7698fdd0807a49588376cfefae5289e4488sewardj            Addr  d = ((Addr)dst) + n; \
271650cf7698fdd0807a49588376cfefae5289e4488sewardj            Addr  s = ((Addr)src) + n; \
272650cf7698fdd0807a49588376cfefae5289e4488sewardj            \
273650cf7698fdd0807a49588376cfefae5289e4488sewardj            /* Copying forwards. */ \
274650cf7698fdd0807a49588376cfefae5289e4488sewardj            if (((s^d) & WM) == 0) { \
275650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* s and d have same UWord alignment. */ \
276650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* Back down to a UWord boundary. */ \
277650cf7698fdd0807a49588376cfefae5289e4488sewardj               while ((s & WM) != 0 && n >= 1) \
278650cf7698fdd0807a49588376cfefae5289e4488sewardj                  { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
279650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* Copy UWords. */ \
280650cf7698fdd0807a49588376cfefae5289e4488sewardj               while (n >= WS) \
281650cf7698fdd0807a49588376cfefae5289e4488sewardj                  { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \
282650cf7698fdd0807a49588376cfefae5289e4488sewardj               if (n == 0) \
283650cf7698fdd0807a49588376cfefae5289e4488sewardj                  return dst; \
284650cf7698fdd0807a49588376cfefae5289e4488sewardj            } \
285650cf7698fdd0807a49588376cfefae5289e4488sewardj            if (((s|d) & 1) == 0) { \
286650cf7698fdd0807a49588376cfefae5289e4488sewardj               /* Both are 16-aligned; copy what we can thusly. */ \
287650cf7698fdd0807a49588376cfefae5289e4488sewardj               while (n >= 2) \
288650cf7698fdd0807a49588376cfefae5289e4488sewardj                  { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \
289650cf7698fdd0807a49588376cfefae5289e4488sewardj            } \
290650cf7698fdd0807a49588376cfefae5289e4488sewardj            /* Copy leftovers, or everything if misaligned. */ \
291650cf7698fdd0807a49588376cfefae5289e4488sewardj            while (n >= 1) \
292650cf7698fdd0807a49588376cfefae5289e4488sewardj               { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \
293650cf7698fdd0807a49588376cfefae5289e4488sewardj            \
294650cf7698fdd0807a49588376cfefae5289e4488sewardj         } \
295024598e40c84666cc311a42c256bbf880db3ac99sewardj      } \
296650cf7698fdd0807a49588376cfefae5289e4488sewardj      \
297650cf7698fdd0807a49588376cfefae5289e4488sewardj      return dst; \
298024598e40c84666cc311a42c256bbf880db3ac99sewardj   }
299024598e40c84666cc311a42c256bbf880db3ac99sewardj
300e61546621e9bca129420399d7c552f8f63c93509njnMEMCPY(VG_Z_LIBC_SONAME, memcpy)
301b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#if defined(VGO_linux)
302e61546621e9bca129420399d7c552f8f63c93509njnMEMCPY(VG_Z_LD_SO_1,     memcpy) /* ld.so.1 */
303e61546621e9bca129420399d7c552f8f63c93509njnMEMCPY(VG_Z_LD64_SO_1,   memcpy) /* ld64.so.1 */
304b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#endif
305024598e40c84666cc311a42c256bbf880db3ac99sewardj
306024598e40c84666cc311a42c256bbf880db3ac99sewardj
307dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj/* Copy SRC to DEST, returning the address of the terminating '\0' in
308dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   DEST. (minor variant of strcpy) */
309dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj#define STPCPY(soname, fnname) \
310dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \
311dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \
312dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   { \
313dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      while (*src) *dst++ = *src++; \
314dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      *dst = 0; \
315dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      \
316dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj      return dst; \
317dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj   }
318dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj
319e61546621e9bca129420399d7c552f8f63c93509njnSTPCPY(VG_Z_LIBC_SONAME,          stpcpy)
320b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#if defined(VGO_linux)
321e61546621e9bca129420399d7c552f8f63c93509njnSTPCPY(VG_Z_LD_LINUX_SO_2,        stpcpy)
322e61546621e9bca129420399d7c552f8f63c93509njnSTPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
323b4cfbc4e32d5dbf71de9b267ed18462a23d1747fnjn#endif
324dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj
325dda0df8bb606946e7546cd6cf5cbfa1aa3aafdcdsewardj
326da387f2a63296760a87ce4b929fe7f95c52567bbsewardj/* Find the first occurrence of C in S.  */
327da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#define GLIBC232_RAWMEMCHR(soname, fnname) \
328654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \
329654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \
330da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   { \
331654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      UChar c = (UChar)c_in; \
332654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const UChar* char_ptr = s; \
333da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      while (1) { \
33470a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian         if (*char_ptr == c) return CONST_CAST(void *,char_ptr);   \
335da387f2a63296760a87ce4b929fe7f95c52567bbsewardj         char_ptr++; \
336da387f2a63296760a87ce4b929fe7f95c52567bbsewardj      } \
337da387f2a63296760a87ce4b929fe7f95c52567bbsewardj   }
338da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
339da387f2a63296760a87ce4b929fe7f95c52567bbsewardjGLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
340da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#if defined (VGO_linux)
341da387f2a63296760a87ce4b929fe7f95c52567bbsewardjGLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
342da387f2a63296760a87ce4b929fe7f95c52567bbsewardj#endif
343da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
344da387f2a63296760a87ce4b929fe7f95c52567bbsewardj
345adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj#define STRSTR(soname, fnname) \
346654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
347654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian         (const char* haystack, const char* needle); \
348654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
349654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian         (const char* haystack, const char* needle) \
350adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj   { \
351654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* h = haystack; \
352654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* n = needle; \
353adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      \
354adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      /* find the length of n, not including terminating zero */ \
355adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      UWord nlen = 0; \
356adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      while (n[nlen]) nlen++; \
357adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      \
358adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      /* if n is the empty string, match immediately. */ \
35970a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian      if (nlen == 0) return CONST_CAST(HChar *,h);         \
360adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      \
361adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      /* assert(nlen >= 1); */ \
362654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      HChar n0 = n[0]; \
363adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      \
364adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      while (1) { \
365654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian         const HChar hh = *h; \
366adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         if (hh == 0) return NULL; \
367adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         if (hh != n0) { h++; continue; } \
368adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         \
369adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         UWord i; \
370adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         for (i = 0; i < nlen; i++) { \
371adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj            if (n[i] != h[i]) \
372adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj               break; \
373adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         } \
374adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         /* assert(i >= 0 && i <= nlen); */ \
375adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         if (i == nlen) \
37670a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian            return CONST_CAST(HChar *,h);          \
377adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         \
378adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj         h++; \
379adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj      } \
380adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj   }
381adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj
382adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj#if defined(VGO_linux)
383adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardjSTRSTR(VG_Z_LIBC_SONAME,          strstr)
384adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj#endif
385adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj
386adf9e4dbdfc602e43c466d3ac44082ca6b9cd4fasewardj
3875446faae7a3c883418549573d8e74f80c2a9b8a8sewardj#define STRPBRK(soname, fnname) \
388654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
389654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian         (const char* sV, const char* acceptV); \
390654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
391654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian         (const char* sV, const char* acceptV) \
3925446faae7a3c883418549573d8e74f80c2a9b8a8sewardj   { \
393654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* s = sV; \
394654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian      const HChar* accept = acceptV; \
3955446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      \
3965446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      /*  find the length of 'accept', not including terminating zero */ \
3975446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      UWord nacc = 0; \
3985446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      while (accept[nacc]) nacc++; \
3995446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      \
4005446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      /* if n is the empty string, fail immediately. */ \
4015446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      if (nacc == 0) return NULL; \
4025446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      \
4035446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      /* assert(nacc >= 1); */ \
4045446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      while (1) { \
4055446faae7a3c883418549573d8e74f80c2a9b8a8sewardj         UWord i; \
406654b542166d7f2e8e89f1cd8430e7ed2ba96f230florian         HChar sc = *s; \
4075446faae7a3c883418549573d8e74f80c2a9b8a8sewardj         if (sc == 0) \
4085446faae7a3c883418549573d8e74f80c2a9b8a8sewardj            break; \
4095446faae7a3c883418549573d8e74f80c2a9b8a8sewardj         for (i = 0; i < nacc; i++) { \
4105446faae7a3c883418549573d8e74f80c2a9b8a8sewardj            if (sc == accept[i]) \
41170a5de1d6c1a5c74b91b564b0ead8ae8a460173cflorian               return CONST_CAST(HChar *,s);       \
4125446faae7a3c883418549573d8e74f80c2a9b8a8sewardj         } \
4135446faae7a3c883418549573d8e74f80c2a9b8a8sewardj         s++; \
4145446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      } \
4155446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      \
4165446faae7a3c883418549573d8e74f80c2a9b8a8sewardj      return NULL; \
4175446faae7a3c883418549573d8e74f80c2a9b8a8sewardj   }
4185446faae7a3c883418549573d8e74f80c2a9b8a8sewardj
4195446faae7a3c883418549573d8e74f80c2a9b8a8sewardj#if defined(VGO_linux)
4205446faae7a3c883418549573d8e74f80c2a9b8a8sewardjSTRPBRK(VG_Z_LIBC_SONAME,          strpbrk)
4215446faae7a3c883418549573d8e74f80c2a9b8a8sewardj#endif
4225446faae7a3c883418549573d8e74f80c2a9b8a8sewardj
4235446faae7a3c883418549573d8e74f80c2a9b8a8sewardj
424024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
425024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- end                                          pc_intercepts.c ---*/
426024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--------------------------------------------------------------------*/
427