1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Replacements for strcpy(), memcpy() et al, which run on the ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- simulated CPU. ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- mc_replace_strmem.c ---*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of MemCheck, a heavyweight Valgrind tool for 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detecting memory errors. 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 Julian Seward 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_hashtable.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_redir.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "valgrind.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mc_include.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "memcheck.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We have our own versions of these functions for two reasons: 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (a) it allows us to do overlap checking 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (b) some of the normal versions are hyper-optimised, which fools 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Memcheck and cause spurious value warnings. Our versions are 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simpler. 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that overenthusiastic use of PLT bypassing by the glibc people also 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown means that we need to patch multiple versions of some of the functions to 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown our own implementations. 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown THEY RUN ON THE SIMD CPU! 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Assignment of behavioural equivalence class tags: 2NNNP is intended 57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to be reserved for Memcheck. Current usage: 58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20010 STRRCHR 60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20020 STRCHR 61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20030 STRCAT 62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20040 STRNCAT 63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20050 STRLCAT 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20060 STRNLEN 65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20070 STRLEN 66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20080 STRCPY 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20090 STRNCPY 68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20100 STRLCPY 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20110 STRNCMP 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20120 STRCASECMP 71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20130 STRNCASECMP 72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20140 STRCASECMP_L 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20150 STRNCASECMP_L 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20160 STRCMP 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20170 MEMCHR 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20180 MEMCPY if there's a conflict between memcpy and 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20181 MEMMOVE memmove, prefer memmove 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20190 MEMCMP 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20200 STPCPY 82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20210 MEMSET 83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2022P unused (was previously MEMMOVE) 84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20230 BCOPY 85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20240 GLIBC25___MEMMOVE_CHK 86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20250 GLIBC232_STRCHRNUL 87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20260 GLIBC232_RAWMEMCHR 88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20270 GLIBC25___STRCPY_CHK 89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20280 GLIBC25___STPCPY_CHK 90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20290 GLIBC25_MEMPCPY 91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20300 GLIBC26___MEMCPY_CHK 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20310 STRSTR 93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20320 STRPBRK 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20330 STRCSPN 95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20340 STRSPN 96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 20350 STRCASESTR 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/ 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if [dst .. dst+dstlen-1] overlaps with 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [src .. src+srclen-1]. 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We assume that the address ranges do not wrap around 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (which is safe since on Linux addresses >= 0xC0000000 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are not accessible and the program will segfault in this 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown circumstance, presumably). 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen ) 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr loS, hiS, loD, hiD; 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dstlen == 0 || srclen == 0) 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loS = (Addr)src; 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loD = (Addr)dst; 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hiS = loS + srclen - 1; 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hiD = loD + dstlen - 1; 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So figure out if [loS .. hiS] overlaps with [loD .. hiD]. */ 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (loS < loD) { 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return !(hiS < loD); 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (loD < loS) { 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return !(hiD < loS); 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* They start at same place. Since we know neither of them has 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zero length, they must overlap. */ 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Call here to exit if we can't continue. On Android we can't call 136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov _exit for some reason, so we have to blunt-instrument it. */ 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__ ((__noreturn__)) 138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline void my_exit ( int x ) 139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGPV_arm_linux_android) 141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov __asm__ __volatile__(".word 0xFFFFFFFF"); 142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (1) {} 143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov extern __attribute__ ((__noreturn__)) void _exit(int status); 145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov _exit(x); 146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is a macro rather than a function because we don't want to have an 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// extra function in the stack trace. 152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define RECORD_OVERLAP_ERROR(s, src, dst, len) \ 153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_DO_CLIENT_REQUEST_STMT( \ 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR, \ 155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s, src, dst, len, 0) 156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strrchr ----------------------*/ 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRRCHR(soname, fnname) \ 161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ); \ 162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20010,soname,fnname)( const char* s, int c ) \ 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar ch = (UChar)((UInt)c); \ 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)s; \ 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* last = NULL; \ 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { \ 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == ch) last = p; \ 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == 0) return last; \ 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p++; \ 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Apparently rindex() is the same thing as strrchr() 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME, strrchr) 177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME, rindex) 178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) 179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LD_LINUX_SO_2, rindex) 180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRRCHR(VG_Z_LIBC_SONAME, strrchr) 183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME, rindex) 184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_DYLD, strrchr) 185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_DYLD, rindex) 186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRRCHR(VG_Z_LIBC_SONAME, strrchr) 187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strchr ----------------------*/ 192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCHR(soname, fnname) \ 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ); \ 195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20020,soname,fnname) ( const char* s, int c ) \ 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar ch = (UChar)((UInt)c); \ 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)s; \ 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { \ 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == ch) return p; \ 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == 0) return NULL; \ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p++; \ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Apparently index() is the same thing as strchr() 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME, strchr) 209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME, index) 210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) 211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGP_x86_linux) 212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_SO_2, strchr) 213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_SO_2, index) 214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) 215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) 216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRCHR(VG_Z_LIBC_SONAME, strchr) 220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME, index) 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_DYLD, strchr) 222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_DYLD, index) 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME, strchr) 224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcat ----------------------*/ 229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCAT(soname, fnname) \ 231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ 232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( char* dst, const char* src ); \ 233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20030,soname,fnname) \ 234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( char* dst, const char* src ) \ 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* src_orig = src; \ 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst_orig = dst; \ 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*dst) dst++; \ 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*src) *dst++ = *src++; \ 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dst = 0; \ 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is a bit redundant, I think; any overlap and the strcat will */ \ 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* go forever... or until a seg fault occurs. */ \ 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, \ 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown src_orig, \ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)dst-(Addr)dst_orig+1, \ 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)src-(Addr)src_orig+1)) \ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("strcat", dst_orig, src_orig, 0); \ 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst_orig; \ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCAT(VG_Z_LIBC_SONAME, strcat) 255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) 256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCAT(VG_Z_LIBC_SONAME, strcat) 259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncat ----------------------*/ 264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNCAT(soname, fnname) \ 266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ); \ 268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20040,soname,fnname) \ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ) \ 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* src_orig = src; \ 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst_orig = dst; \ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m = 0; \ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*dst) dst++; \ 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m < n && *src) { m++; *dst++ = *src++; } /* concat <= n chars */ \ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dst = 0; /* always add null */ \ 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This checks for overlap after copying, unavoidable without */ \ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pre-counting lengths... should be ok */ \ 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, \ 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown src_orig, \ 283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (Addr)dst-(Addr)dst_orig+1, \ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)src-(Addr)src_orig+1)) \ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("strncat", dst_orig, src_orig, n); \ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst_orig; \ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCAT(VG_Z_LIBC_SONAME, strncat) 292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCAT(VG_Z_LIBC_SONAME, strncat) 295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCAT(VG_Z_DYLD, strncat) 296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strlcat ----------------------*/ 301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Append src to dst. n is the size of dst's buffer. dst is guaranteed 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to be nul-terminated after the copy, unless n <= strlen(dst_orig). 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns min(n, strlen(dst_orig)) + strlen(src_orig). 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Truncation occurred if retval >= n. 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLCAT(soname, fnname) \ 308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ); \ 310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20050,soname,fnname) \ 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ) \ 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* src_orig = src; \ 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst_orig = dst; \ 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m = 0; \ 316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m < n && *dst) { m++; dst++; } \ 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (m < n) { \ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fill as far as dst_orig[n-2], then nul-terminate. */ \ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m < n-1 && *src) { m++; *dst++ = *src++; } \ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dst = 0; \ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { \ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* No space to copy anything to dst. m == n */ \ 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finish counting min(n, strlen(dst_orig)) + strlen(src_orig) */ \ 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*src) { m++; src++; } \ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This checks for overlap after copying, unavoidable without */ \ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pre-counting lengths... should be ok */ \ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, \ 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown src_orig, \ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)dst-(Addr)dst_orig+1, \ 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)src-(Addr)src_orig+1)) \ 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("strlcat", dst_orig, src_orig, n); \ 334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return m; \ 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRLCAT(VG_Z_LIBC_SONAME, strlcat) 342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLCAT(VG_Z_DYLD, strlcat) 343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLCAT(VG_Z_LIBC_SONAME, strlcat) 344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strnlen ----------------------*/ 349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNLEN(soname, fnname) \ 351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ 352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( const char* str, SizeT n ); \ 353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20060,soname,fnname) \ 354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( const char* str, SizeT n ) \ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT i = 0; \ 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i < n && str[i] != 0) i++; \ 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i; \ 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNLEN(VG_Z_LIBC_SONAME, strnlen) 363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen) 364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNLEN(VG_Z_LIBC_SONAME, strnlen) 367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strlen ----------------------*/ 372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note that this replacement often doesn't get used because gcc inlines 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// calls to strlen() with its own built-in version. This can be very 375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// confusing if you aren't expecting it. Other small functions in 376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// this file may also be inline by gcc. 377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLEN(soname, fnname) \ 379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ 380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( const char* str ); \ 381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20070,soname,fnname) \ 382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( const char* str ) \ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT i = 0; \ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (str[i] != 0) i++; \ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i; \ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME, strlen) 391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) 392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGPV_arm_linux_android) 393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(NONE, __dl_strlen); /* in /system/bin/linker */ 394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRLEN(VG_Z_LIBC_SONAME, strlen) 398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME, strlen) 399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcpy ----------------------*/ 404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCPY(soname, fnname) \ 406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ 407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( char* dst, const char* src ); \ 408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20080,soname,fnname) \ 409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( char* dst, const char* src ) \ 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* src_orig = src; \ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst_orig = dst; \ 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*src) *dst++ = *src++; \ 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dst = 0; \ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This checks for overlap after copying, unavoidable without */ \ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pre-counting length... should be ok */ \ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, \ 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown src_orig, \ 421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (Addr)dst-(Addr)dst_orig+1, \ 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)src-(Addr)src_orig+1)) \ 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("strcpy", dst_orig, src_orig, 0); \ 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst_orig; \ 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, strcpy) 430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) 431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRCPY(VG_Z_LIBC_SONAME, strcpy) 434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_DYLD, strcpy) 435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, strcpy) 436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncpy ----------------------*/ 441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNCPY(soname, fnname) \ 443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ); \ 445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20090,soname,fnname) \ 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ) \ 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* src_orig = src; \ 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst_orig = dst; \ 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m = 0; \ 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m < n && *src) { m++; *dst++ = *src++; } \ 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* but only m+1 bytes of src if terminator was found */ \ 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("strncpy", dst, src, n); \ 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m++ < n) *dst++ = 0; /* must pad remainder with nulls */ \ 458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst_orig; \ 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_LIBC_SONAME, strncpy) 464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy) 465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRNCPY(VG_Z_LIBC_SONAME, strncpy) 468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_DYLD, strncpy) 469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCPY(VG_Z_LIBC_SONAME, strncpy) 470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strlcpy ----------------------*/ 475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy up to n-1 bytes from src to dst. Then nul-terminate dst if n > 0. 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns strlen(src). Does not zero-fill the remainder of dst. */ 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLCPY(soname, fnname) \ 479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ); \ 481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20100,soname,fnname) \ 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( char* dst, const char* src, SizeT n ) \ 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char* src_orig = src; \ 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char* dst_orig = dst; \ 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT m = 0; \ 487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m < n-1 && *src) { m++; *dst++ = *src++; } \ 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* m non-nul bytes have now been copied, and m <= n-1. */ \ 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check for overlap after copying; all n bytes of dst are relevant, */ \ 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* but only m+1 bytes of src if terminator was found */ \ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, src_orig, n, (m < n) ? m+1 : n)) \ 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("strlcpy", dst, src, n); \ 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Nul-terminate dst. */ \ 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n > 0) *dst = 0; \ 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finish counting strlen(src). */ \ 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*src) src++; \ 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return src - src_orig; \ 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRLCPY(VG_Z_LIBC_SONAME, strlcpy) 505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLCPY(VG_Z_DYLD, strlcpy) 506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLCPY(VG_Z_LIBC_SONAME, strlcpy) 507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncmp ----------------------*/ 512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRNCMP(soname, fnname) \ 514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( const char* s1, const char* s2, SizeT nmax ); \ 516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20110,soname,fnname) \ 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( const char* s1, const char* s2, SizeT nmax ) \ 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT n = 0; \ 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { \ 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n >= nmax) return 0; \ 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*s1 == 0 && *s2 == 0) return 0; \ 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*s1 == 0) return -1; \ 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*s2 == 0) return 1; \ 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*(unsigned char*)s1 < *(unsigned char*)s2) return -1; \ 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*(unsigned char*)s1 > *(unsigned char*)s2) return 1; \ 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1++; s2++; n++; \ 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_LIBC_SONAME, strncmp) 535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) 536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRNCMP(VG_Z_LIBC_SONAME, strncmp) 539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_DYLD, strncmp) 540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCMP(VG_Z_LIBC_SONAME, strncmp) 541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcasecmp ----------------------*/ 546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 547f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRCASECMP(soname, fnname) \ 548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ 549f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2 ); \ 550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20120,soname,fnname) \ 551f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2 ) \ 552f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root { \ 553f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root extern int tolower(int); \ 554f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root register unsigned char c1; \ 555f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root register unsigned char c2; \ 556f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root while (True) { \ 557f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root c1 = tolower(*(unsigned char *)s1); \ 558f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root c2 = tolower(*(unsigned char *)s2); \ 559f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (c1 != c2) break; \ 560f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (c1 == 0) break; \ 561f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root s1++; s2++; \ 562f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } \ 563f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 564f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 565f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return 0; \ 566f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 567f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 568f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux) 569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGPV_arm_linux_android) 570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) 571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP(VG_Z_LIBC_SONAME, __GI_strcasecmp) 572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP(VG_Z_LIBC_SONAME, strcasecmp) 576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 577f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif 578f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 579f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncasecmp ----------------------*/ 581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 582f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRNCASECMP(soname, fnname) \ 583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ 584f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2, SizeT nmax ); \ 585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20130,soname,fnname) \ 586f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2, SizeT nmax ) \ 587f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root { \ 588f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root extern int tolower(int); \ 589f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root SizeT n = 0; \ 590f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root while (True) { \ 591f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (n >= nmax) return 0; \ 592f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (*s1 == 0 && *s2 == 0) return 0; \ 593f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (*s1 == 0) return -1; \ 594f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (*s2 == 0) return 1; \ 595f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root \ 596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tolower(*(unsigned char*)s1) \ 597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov < tolower(*(unsigned char*)s2)) return -1; \ 598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tolower(*(unsigned char*)s1) \ 599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov > tolower(*(unsigned char*)s2)) return 1; \ 600f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root \ 601f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root s1++; s2++; n++; \ 602f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } \ 603f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 604f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 605f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux) 606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if !defined(VGPV_arm_linux_android) 607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) 608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP(VG_Z_LIBC_SONAME, __GI_strncasecmp) 609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 611f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#elif defined(VGO_darwin) 612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP(VG_Z_LIBC_SONAME, strncasecmp) 613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP(VG_Z_DYLD, strncasecmp) 614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 615f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif 616f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 617f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcasecmp_l ----------------------*/ 619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 620f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRCASECMP_L(soname, fnname) \ 621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ 622f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2, void* locale ); \ 623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20140,soname,fnname) \ 624f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2, void* locale ) \ 625f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root { \ 626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov extern int tolower_l(int, void*) __attribute__((weak)); \ 627f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root register unsigned char c1; \ 628f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root register unsigned char c2; \ 629f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root while (True) { \ 630f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root c1 = tolower_l(*(unsigned char *)s1, locale); \ 631f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root c2 = tolower_l(*(unsigned char *)s2, locale); \ 632f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (c1 != c2) break; \ 633f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (c1 == 0) break; \ 634f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root s1++; s2++; \ 635f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } \ 636f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 637f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 638f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return 0; \ 639f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 640f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 641f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux) 642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) 643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, __GI_strcasecmp_l) 644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, __GI___strcasecmp_l) 645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASECMP_L(VG_Z_LIBC_SONAME, strcasecmp_l) 648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 649f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif 650f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 651f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strncasecmp_l ----------------------*/ 653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 654f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define STRNCASECMP_L(soname, fnname) \ 655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ 656f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2, SizeT nmax, void* locale ); \ 657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20150,soname,fnname) \ 658f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root ( const char* s1, const char* s2, SizeT nmax, void* locale ) \ 659f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root { \ 660f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root extern int tolower_l(int, void*) __attribute__((weak)); \ 661f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root SizeT n = 0; \ 662f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root while (True) { \ 663f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (n >= nmax) return 0; \ 664f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (*s1 == 0 && *s2 == 0) return 0; \ 665f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (*s1 == 0) return -1; \ 666f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (*s2 == 0) return 1; \ 667f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root \ 668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tolower_l(*(unsigned char*)s1, locale) \ 669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov < tolower_l(*(unsigned char*)s2, locale)) return -1; \ 670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tolower_l(*(unsigned char*)s1, locale) \ 671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov > tolower_l(*(unsigned char*)s2, locale)) return 1; \ 672f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root \ 673f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root s1++; s2++; n++; \ 674f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } \ 675f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 676f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 677f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#if defined(VGO_linux) 678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) 679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP_L(VG_Z_LIBC_SONAME, __GI_strncasecmp_l) 680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 681f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#elif defined(VGO_darwin) 682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP_L(VG_Z_LIBC_SONAME, strncasecmp_l) 683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRNCASECMP_L(VG_Z_DYLD, strncasecmp_l) 684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 685f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#endif 686f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 687f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcmp ----------------------*/ 689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCMP(soname, fnname) \ 691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( const char* s1, const char* s2 ); \ 693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20160,soname,fnname) \ 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( const char* s1, const char* s2 ) \ 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register unsigned char c1; \ 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register unsigned char c2; \ 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { \ 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c1 = *(unsigned char *)s1; \ 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c2 = *(unsigned char *)s2; \ 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c1 != c2) break; \ 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c1 == 0) break; \ 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1++; s2++; \ 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((unsigned char)c1 < (unsigned char)c2) return -1; \ 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((unsigned char)c1 > (unsigned char)c2) return 1; \ 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; \ 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME, strcmp) 712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) 713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) 714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LD64_SO_1, strcmp) 715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGPV_arm_linux_android) 716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(NONE, __dl_strcmp); /* in /system/bin/linker */ 717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //STRCMP(VG_Z_LIBC_SONAME, strcmp) 721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME, strcmp) 722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memchr ----------------------*/ 727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMCHR(soname, fnname) \ 729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ 730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (const void *s, int c, SizeT n); \ 731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20170,soname,fnname) \ 732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (const void *s, int c, SizeT n) \ 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT i; \ 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar c0 = (UChar)c; \ 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p = (UChar*)s; \ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) \ 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p[i] == c0) return (void*)(&p[i]); \ 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; \ 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCHR(VG_Z_LIBC_SONAME, memchr) 744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCHR(VG_Z_LIBC_SONAME, memchr) 747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCHR(VG_Z_DYLD, memchr) 748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memcpy ----------------------*/ 753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MEMMOVE_OR_MEMCPY(becTag, soname, fnname, do_ol_check) \ 755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( void *dst, const void *src, SizeT len ); \ 757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZZ(becTag,soname,fnname) \ 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( void *dst, const void *src, SizeT len ) \ 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (do_ol_check && is_overlap(dst, src, len, len)) \ 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("memcpy", dst, src, len); \ 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Addr WS = sizeof(UWord); /* 8 or 4 */ \ 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Addr WM = WS - 1; /* 7 or 3 */ \ 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (len > 0) { \ 767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (dst < src) { \ 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Copying backwards. */ \ 770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT n = len; \ 771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr d = (Addr)dst; \ 772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr s = (Addr)src; \ 773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (((s^d) & WM) == 0) { \ 775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* s and d have same UWord alignment. */ \ 776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Pull up to a UWord boundary. */ \ 777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while ((s & WM) != 0 && n >= 1) \ 778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Copy UWords. */ \ 780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n >= WS) \ 781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \ 782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (n == 0) \ 783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return dst; \ 784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (((s|d) & 1) == 0) { \ 786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Both are 16-aligned; copy what we can thusly. */ \ 787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n >= 2) \ 788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \ 789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Copy leftovers, or everything if misaligned. */ \ 791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n >= 1) \ 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (dst > src) { \ 795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT n = len; \ 797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr d = ((Addr)dst) + n; \ 798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr s = ((Addr)src) + n; \ 799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Copying forwards. */ \ 801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (((s^d) & WM) == 0) { \ 802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* s and d have same UWord alignment. */ \ 803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Back down to a UWord boundary. */ \ 804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while ((s & WM) != 0 && n >= 1) \ 805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Copy UWords. */ \ 807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n >= WS) \ 808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \ 809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (n == 0) \ 810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return dst; \ 811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (((s|d) & 1) == 0) { \ 813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Both are 16-aligned; copy what we can thusly. */ \ 814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n >= 2) \ 815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \ 816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Copy leftovers, or everything if misaligned. */ \ 818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n >= 1) \ 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ 820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; \ 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MEMMOVE(soname, fnname) \ 828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE_OR_MEMCPY(20181, soname, fnname, 0) 829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MEMCPY(soname, fnname) \ 831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE_OR_MEMCPY(20180, soname, fnname, 1) 832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* For older memcpy we have to use memmove-like semantics and skip 835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the overlap check; sigh; see #275284. */ 836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memcpyZAGLIBCZu2Zd2Zd5) /* memcpy@GLIBC_2.2.5 */ 837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME, memcpyZAZAGLIBCZu2Zd14) /* memcpy@@GLIBC_2.14 */ 838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME, memcpy) /* fallback case */ 839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ 840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ 841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* icc9 blats these around all over the place. Not only in the main 842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov executable but various .so's. They are highly tuned and read 843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov memory beyond the source boundary (although work correctly and 844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov never go across page boundaries), so give errors when run 845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov natively, at least for misaligned source arg. Just intercepting 846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov in the exe only until we understand more about the problem. See 847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov http://bugs.kde.org/show_bug.cgi?id=139776 848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(NONE, ZuintelZufastZumemcpy) 850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // glider: see https://bugs.kde.org/show_bug.cgi?id=285662 853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME, memcpy) 854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_DYLD, memcpy) 855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse3x) /* memcpy$VARIANT$sse3x */ 856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME, memcpyZDVARIANTZDsse42) /* memcpy$VARIANT$sse42 */ 857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memcmp ----------------------*/ 862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMCMP(soname, fnname) \ 864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( const void *s1V, const void *s2V, SizeT n ); \ 866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int VG_REPLACE_FUNCTION_EZU(20190,soname,fnname) \ 867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( const void *s1V, const void *s2V, SizeT n ) \ 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int res; \ 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char a0; \ 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char b0; \ 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char* s1 = (unsigned char*)s1V; \ 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char* s2 = (unsigned char*)s2V; \ 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (n != 0) { \ 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a0 = s1[0]; \ 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b0 = s2[0]; \ 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s1 += 1; \ 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s2 += 1; \ 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = ((int)a0) - ((int)b0); \ 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res != 0) \ 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; \ 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n -= 1; \ 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; \ 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LIBC_SONAME, memcmp) 890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LIBC_SONAME, bcmp) 891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LD_SO_1, bcmp) 892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LIBC_SONAME, memcmp) 895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_LIBC_SONAME, bcmp) 896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_DYLD, memcmp) 897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCMP(VG_Z_DYLD, bcmp) 898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- stpcpy ----------------------*/ 903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy SRC to DEST, returning the address of the terminating '\0' in 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEST. (minor variant of strcpy) */ 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STPCPY(soname, fnname) \ 907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ 908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( char* dst, const char* src ); \ 909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20200,soname,fnname) \ 910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ( char* dst, const char* src ) \ 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* src_orig = src; \ 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst_orig = dst; \ 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*src) *dst++ = *src++; \ 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *dst = 0; \ 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This checks for overlap after copying, unavoidable without */ \ 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pre-counting length... should be ok */ \ 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst_orig, \ 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown src_orig, \ 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)dst-(Addr)dst_orig+1, \ 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)src-(Addr)src_orig+1)) \ 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("stpcpy", dst_orig, src_orig, 0); \ 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; \ 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LIBC_SONAME, stpcpy) 931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy) 932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) 933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) 934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_LIBC_SONAME, stpcpy) 937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STPCPY(VG_Z_DYLD, stpcpy) 938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memset ----------------------*/ 943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Why are we bothering to intercept this? It seems entirely 945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pointless. */ 946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMSET(soname, fnname) \ 948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ 949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void *s, Int c, SizeT n); \ 950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20210,soname,fnname) \ 951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void *s, Int c, SizeT n) \ 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a = (Addr)s; \ 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt c4 = (c & 0xFF); \ 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c4 = (c4 << 8) | c4; \ 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c4 = (c4 << 16) | c4; \ 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ((a & 3) != 0 && n >= 1) \ 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (n >= 4) \ 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { *(UInt*)a = c4; a += 4; n -= 4; } \ 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (n >= 1) \ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { *(UChar*)a = (UChar)c; a += 1; n -= 1; } \ 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return s; \ 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMSET(VG_Z_LIBC_SONAME, memset) 968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //MEMSET(VG_Z_LIBC_SONAME, memset) 971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMSET(VG_Z_DYLD, memset) 972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMSET(VG_Z_LIBC_SONAME, memset) 973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- memmove ----------------------*/ 978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* memmove -- use the MEMMOVE defn above. */ 980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memmove) 983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // glider: see https://bugs.kde.org/show_bug.cgi?id=285662 986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memmove) 987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_DYLD, memmove) 988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse3x) /* memmove$VARIANT$sse3x */ 989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMMOVE(VG_Z_LIBC_SONAME, memmoveZDVARIANTZDsse42) /* memmove$VARIANT$sse42 */ 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- bcopy ----------------------*/ 995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BCOPY(soname, fnname) \ 997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (const void *srcV, void *dstV, SizeT n); \ 999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void VG_REPLACE_FUNCTION_EZU(20230,soname,fnname) \ 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (const void *srcV, void *dstV, SizeT n) \ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT i; \ 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst = (Char*)dstV; \ 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* src = (Char*)srcV; \ 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dst < src) { \ 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) \ 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst[i] = src[i]; \ 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else \ 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dst > src) { \ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) \ 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst[n-i-1] = src[n-i-1]; \ 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// kcc: enabled bcopy interceptor on non-mac targets. 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBCOPY(VG_Z_LIBC_SONAME, bcopy) 1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov //BCOPY(VG_Z_LIBC_SONAME, bcopy) 1022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov BCOPY(VG_Z_DYLD, bcopy) 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*-------------------- memmove_chk --------------------*/ 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* glibc 2.5 variant of memmove which checks the dest is big enough. 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There is no specific part of glibc that this is copied from. */ 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25___MEMMOVE_CHK(soname, fnname) \ 1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void *dstV, const void *srcV, SizeT n, SizeT destlen); \ 1032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20240,soname,fnname) \ 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void *dstV, const void *srcV, SizeT n, SizeT destlen) \ 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT i; \ 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dst = (Char*)dstV; \ 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* src = (Char*)srcV; \ 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (destlen < n) \ 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto badness; \ 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dst < src) { \ 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) \ 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst[i] = src[i]; \ 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else \ 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dst > src) { \ 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n; i++) \ 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst[n-i-1] = src[n-i-1]; \ 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; \ 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown badness: \ 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_PRINTF_BACKTRACE( \ 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "*** memmove_chk: buffer overflow detected ***: " \ 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "program terminated\n"); \ 1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov my_exit(127); \ 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ \ 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; \ 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25___MEMMOVE_CHK(VG_Z_LIBC_SONAME, __memmove_chk) 1061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*-------------------- strchrnul --------------------*/ 1068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the first occurrence of C in S or the final NUL byte. */ 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC232_STRCHRNUL(soname, fnname) \ 1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ 1072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (const char* s, int c_in); \ 1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20250,soname,fnname) \ 1074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (const char* s, int c_in) \ 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char c = (unsigned char) c_in; \ 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char* char_ptr = (unsigned char *)s; \ 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { \ 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*char_ptr == 0) return char_ptr; \ 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*char_ptr == c) return char_ptr; \ 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char_ptr++; \ 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul) 1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- rawmemchr ----------------------*/ 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the first occurrence of C in S. */ 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC232_RAWMEMCHR(soname, fnname) \ 1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ 1098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (const char* s, int c_in); \ 1099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20260,soname,fnname) \ 1100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (const char* s, int c_in) \ 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char c = (unsigned char) c_in; \ 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned char* char_ptr = (unsigned char *)s; \ 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { \ 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*char_ptr == c) return char_ptr; \ 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char_ptr++; \ 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined (VGO_linux) 1111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) 1112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) 1113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcpy_chk ----------------------*/ 1120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* glibc variant of strcpy that checks the dest is big enough. 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copied from glibc-2.5/debug/test-strcpy_chk.c. */ 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25___STRCPY_CHK(soname,fnname) \ 1124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ 1125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (char* dst, const char* src, SizeT len); \ 1126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20270,soname,fnname) \ 1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (char* dst, const char* src, SizeT len) \ 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char* ret = dst; \ 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! len) \ 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto badness; \ 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ((*dst++ = *src++) != '\0') \ 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (--len == 0) \ 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto badness; \ 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; \ 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown badness: \ 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_PRINTF_BACKTRACE( \ 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "*** strcpy_chk: buffer overflow detected ***: " \ 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "program terminated\n"); \ 1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov my_exit(127); \ 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ \ 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; \ 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25___STRCPY_CHK(VG_Z_LIBC_SONAME, __strcpy_chk) 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- stpcpy_chk ----------------------*/ 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* glibc variant of stpcpy that checks the dest is big enough. 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copied from glibc-2.5/debug/test-stpcpy_chk.c. */ 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25___STPCPY_CHK(soname,fnname) \ 1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ 1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (char* dst, const char* src, SizeT len); \ 1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* VG_REPLACE_FUNCTION_EZU(20280,soname,fnname) \ 1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (char* dst, const char* src, SizeT len) \ 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! len) \ 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto badness; \ 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ((*dst++ = *src++) != '\0') \ 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (--len == 0) \ 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto badness; \ 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst - 1; \ 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown badness: \ 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_PRINTF_BACKTRACE( \ 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "*** stpcpy_chk: buffer overflow detected ***: " \ 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "program terminated\n"); \ 1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov my_exit(127); \ 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ \ 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; \ 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25___STPCPY_CHK(VG_Z_LIBC_SONAME, __stpcpy_chk) 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- mempcpy ----------------------*/ 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* mempcpy */ 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC25_MEMPCPY(soname, fnname) \ 1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( void *dst, const void *src, SizeT len ); \ 1192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20290,soname,fnname) \ 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( void *dst, const void *src, SizeT len ) \ 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register char *d; \ 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register char *s; \ 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT len_saved = len; \ 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) \ 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; \ 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst, src, len, len)) \ 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("mempcpy", dst, src, len); \ 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( dst > src ) { \ 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = (char *)dst + len - 1; \ 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s = (char *)src + len - 1; \ 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( len-- ) { \ 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *d-- = *s--; \ 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( dst < src ) { \ 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = (char *)dst; \ 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s = (char *)src; \ 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( len-- ) { \ 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *d++ = *s++; \ 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void*)( ((char*)dst) + len_saved ); \ 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) 1223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25_MEMPCPY(VG_Z_LD_SO_1, mempcpy) /* ld.so.1 */ 1224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC25_MEMPCPY(VG_Z_LIBC_SONAME, mempcpy) 1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*-------------------- memcpy_chk --------------------*/ 1232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define GLIBC26___MEMCPY_CHK(soname, fnname) \ 1234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* dst, const void* src, SizeT len, SizeT dstlen ); \ 1236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20300,soname,fnname) \ 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* dst, const void* src, SizeT len, SizeT dstlen ) \ 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register char *d; \ 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register char *s; \ 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (dstlen < len) goto badness; \ 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (len == 0) \ 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; \ 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_overlap(dst, src, len, len)) \ 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown RECORD_OVERLAP_ERROR("memcpy_chk", dst, src, len); \ 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( dst > src ) { \ 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = (char *)dst + len - 1; \ 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s = (char *)src + len - 1; \ 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( len-- ) { \ 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *d-- = *s--; \ 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( dst < src ) { \ 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d = (char *)dst; \ 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s = (char *)src; \ 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( len-- ) { \ 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *d++ = *s++; \ 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; \ 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown badness: \ 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_PRINTF_BACKTRACE( \ 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "*** memcpy_chk: buffer overflow detected ***: " \ 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "program terminated\n"); \ 1268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov my_exit(127); \ 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ \ 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; \ 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GLIBC26___MEMCPY_CHK(VG_Z_LIBC_SONAME, __memcpy_chk) 1275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strstr ----------------------*/ 1282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRSTR(soname, fnname) \ 1284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* haystack, void* needle); \ 1286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20310,soname,fnname) \ 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* haystack, void* needle) \ 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* h = (UChar*)haystack; \ 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* n = (UChar*)needle; \ 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* find the length of n, not including terminating zero */ \ 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord nlen = 0; \ 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (n[nlen]) nlen++; \ 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if n is the empty string, match immediately. */ \ 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nlen == 0) return h; \ 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assert(nlen >= 1); */ \ 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar n0 = n[0]; \ 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { \ 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar hh = *h; \ 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (hh == 0) return NULL; \ 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (hh != n0) { h++; continue; } \ 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord i; \ 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nlen; i++) { \ 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n[i] != h[i]) \ 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assert(i >= 0 && i <= nlen); */ \ 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i == nlen) \ 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return h; \ 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown h++; \ 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRSTR(VG_Z_LIBC_SONAME, strstr) 1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strpbrk ----------------------*/ 1329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRPBRK(soname, fnname) \ 1331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* sV, void* acceptV); \ 1333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20320,soname,fnname) \ 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* sV, void* acceptV) \ 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* s = (UChar*)sV; \ 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* accept = (UChar*)acceptV; \ 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* find the length of 'accept', not including terminating zero */ \ 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord nacc = 0; \ 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (accept[nacc]) nacc++; \ 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if n is the empty string, fail immediately. */ \ 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nacc == 0) return NULL; \ 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assert(nacc >= 1); */ \ 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { \ 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord i; \ 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar sc = *s; \ 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sc == 0) \ 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nacc; i++) { \ 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sc == accept[i]) \ 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return s; \ 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s++; \ 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; \ 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRPBRK(VG_Z_LIBC_SONAME, strpbrk) 1364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcspn ----------------------*/ 1371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCSPN(soname, fnname) \ 1373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* sV, void* rejectV); \ 1375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20330,soname,fnname) \ 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void* sV, void* rejectV) \ 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { \ 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* s = (UChar*)sV; \ 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* reject = (UChar*)rejectV; \ 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* find the length of 'reject', not including terminating zero */ \ 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord nrej = 0; \ 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (reject[nrej]) nrej++; \ 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord len = 0; \ 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { \ 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord i; \ 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar sc = *s; \ 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sc == 0) \ 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nrej; i++) { \ 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sc == reject[i]) \ 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assert(i >= 0 && i <= nrej); */ \ 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i < nrej) \ 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; \ 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s++; \ 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len++; \ 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } \ 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return len; \ 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCSPN(VG_Z_LIBC_SONAME, strcspn) 1407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strspn ----------------------*/ 1414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define STRSPN(soname, fnname) \ 1416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ 1417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void* sV, void* acceptV); \ 1418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT VG_REPLACE_FUNCTION_EZU(20340,soname,fnname) \ 1419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void* sV, void* acceptV) \ 1420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { \ 1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar* s = (UChar*)sV; \ 1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar* accept = (UChar*)acceptV; \ 1423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* find the length of 'accept', not including terminating zero */ \ 1425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord nacc = 0; \ 1426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (accept[nacc]) nacc++; \ 1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (nacc == 0) return 0; \ 1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord len = 0; \ 1430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (1) { \ 1431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord i; \ 1432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar sc = *s; \ 1433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sc == 0) \ 1434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; \ 1435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < nacc; i++) { \ 1436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sc == accept[i]) \ 1437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; \ 1438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* assert(i >= 0 && i <= nacc); */ \ 1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (i == nacc) \ 1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; \ 1442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov s++; \ 1443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov len++; \ 1444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return len; \ 1447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRSPN(VG_Z_LIBC_SONAME, strspn) 1451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- strcasestr ----------------------*/ 1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define STRCASESTR(soname, fnname) \ 1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ 1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void* haystack, void* needle); \ 1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* VG_REPLACE_FUNCTION_EZU(20350,soname,fnname) \ 1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void* haystack, void* needle) \ 1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { \ 1465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov extern int tolower(int); \ 1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar* h = (UChar*)haystack; \ 1467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar* n = (UChar*)needle; \ 1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* find the length of n, not including terminating zero */ \ 1470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord nlen = 0; \ 1471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (n[nlen]) nlen++; \ 1472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* if n is the empty string, match immediately. */ \ 1474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (nlen == 0) return h; \ 1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* assert(nlen >= 1); */ \ 1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar n0 = tolower(n[0]); \ 1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (1) { \ 1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UChar hh = tolower(*h); \ 1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (hh == 0) return NULL; \ 1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (hh != n0) { h++; continue; } \ 1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord i; \ 1485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < nlen; i++) { \ 1486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tolower(n[i]) != tolower(h[i])) \ 1487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; \ 1488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 1489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* assert(i >= 0 && i <= nlen); */ \ 1490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (i == nlen) \ 1491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return h; \ 1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov \ 1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov h++; \ 1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } \ 1495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 1498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCASESTR(VG_Z_LIBC_SONAME, strcasestr) 1499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin) 1501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Improve definedness checking of process environment ---*/ 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* If these wind up getting generated via a macro, so that multiple 1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov versions of each function exist (as above), use the _EZU variants 1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to assign equivalance class tags. */ 1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- putenv ----------------------*/ 1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string); 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, putenv) (char* string) 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word result; 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char* p = string; 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now by walking over the string we magically produce 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown traces when hitting undefined memory. */ 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p) 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*p++) 1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov __asm__ __volatile__("" ::: "memory"); 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(result, fn, string); 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- unsetenv ----------------------*/ 1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name); 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, unsetenv) (const char* name) 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word result; 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char* p = name; 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now by walking over the string we magically produce 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown traces when hitting undefined memory. */ 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p) 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*p++) 1547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov __asm__ __volatile__("" ::: "memory"); 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(result, fn, name); 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*---------------------- setenv ----------------------*/ 1554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* setenv */ 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (const char* name, const char* value, int overwrite); 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint VG_WRAP_FUNCTION_ZU(VG_Z_LIBC_SONAME, setenv) 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (const char* name, const char* value, int overwrite) 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word result; 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char* p; 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now by walking over the string we magically produce 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown traces when hitting undefined memory. */ 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (name) 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (p = name; *p; p++) 1569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov __asm__ __volatile__("" ::: "memory"); 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (value) 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (p = value; *p; p++) 1572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov __asm__ __volatile__("" ::: "memory"); 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_CHECK_VALUE_IS_DEFINED (overwrite); 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WWW(result, fn, name, value, overwrite); 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif /* defined(VGO_linux) */ 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1583