1 /* 2 This file is part of ThreadSanitizer, a dynamic data race detector 3 based on Valgrind. 4 5 Copyright (C) 2008-2009 Google Inc 6 opensource (at) google.com 7 Copyright (C) 2007-2008 OpenWorks LLP 8 info (at) open-works.co.uk 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License as 12 published by the Free Software Foundation; either version 2 of the 13 License, or (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, but 16 WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 23 02111-1307, USA. 24 25 The GNU General Public License is contained in the file COPYING. 26 */ 27 28 // Author: Konstantin Serebryany. 29 // Parts of the code in this file are derived from Helgrind, 30 // a data race detector written by Julian Seward. 31 // Note that the rest of ThreadSanitizer code is not derived from Helgrind 32 // and is published under the BSD license. 33 34 #define _GNU_SOURCE 1 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <assert.h> 38 #include <errno.h> 39 #include <pthread.h> 40 #include <fcntl.h> // O_CREAT 41 #include <unistd.h> // F_LOCK 42 43 #include "valgrind.h" 44 #include "pub_tool_basics.h" 45 #include "pub_tool_redir.h" 46 #include "pub_tool_threadstate.h" 47 48 #define NOINLINE __attribute__ ((noinline)) 49 50 #include "ts_valgrind_client_requests.h" 51 52 // When replacing a function in valgrind, the replacement code 53 // is instrumented, so we just don't touch reads/writes in replacement 54 // functions. 55 #define EXTRA_REPLACE_PARAMS 56 #define EXTRA_REPLACE_ARGS 57 #define REPORT_READ_RANGE(x, size) 58 #define REPORT_WRITE_RANGE(x, size) 59 #include "ts_replace.h" 60 61 #define TRACE_PTH_FNS 0 62 #define TRACE_ANN_FNS 0 63 64 65 //----------- Basic stuff --------------------------- {{{1 66 67 static inline int VALGRIND_TS_THREAD_ID(void) { 68 unsigned int _qzz_res; 69 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 , 70 TSREQ_GET_THREAD_ID, 71 0, 0, 0, 0, 0); 72 return _qzz_res; 73 } 74 75 static inline int VALGRIND_VG_THREAD_ID(void) { 76 unsigned int _qzz_res; 77 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 , 78 TSREQ_GET_VG_THREAD_ID, 79 0, 0, 0, 0, 0); 80 return _qzz_res; 81 } 82 83 static inline int VALGRIND_TS_SEGMENT_ID(void) { 84 unsigned int _qzz_res; 85 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 , 86 TSREQ_GET_SEGMENT_ID, 87 0, 0, 0, 0, 0); 88 return _qzz_res; 89 } 90 91 #define PTH_FUNC(ret_ty, f, args...) \ 92 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \ 93 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args) 94 95 #define NONE_FUNC(ret_ty, f, args...) \ 96 ret_ty I_WRAP_SONAME_FNNAME_ZZ(NONE,f)(args); \ 97 ret_ty I_WRAP_SONAME_FNNAME_ZZ(NONE,f)(args) 98 99 #define LIBC_FUNC(ret_ty, f, args...) \ 100 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \ 101 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args) 102 103 // libstdcZpZpZa = libstdc++ 104 #define LIBSTDCXX_FUNC(ret_ty, f, args...) \ 105 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBSTDCXX_SONAME,f)(args); \ 106 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBSTDCXX_SONAME,f)(args) 107 108 109 // Do a client request. This is a macro rather than a function 110 // so as to avoid having an extra function in the stack trace. 111 112 #define DO_CREQ_v_v(_creqF) \ 113 do { \ 114 Word _unused_res; \ 115 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \ 116 (_creqF), \ 117 0,0,0,0,0); \ 118 } while (0) 119 120 #define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \ 121 do { \ 122 Word _unused_res, _arg1; \ 123 assert(sizeof(_ty1F) == sizeof(Word)); \ 124 _arg1 = (Word)(_arg1F); \ 125 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \ 126 (_creqF), \ 127 _arg1, 0,0,0,0); \ 128 } while (0) 129 130 #define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \ 131 do { \ 132 Word _unused_res, _arg1, _arg2; \ 133 assert(sizeof(_ty1F) == sizeof(Word)); \ 134 assert(sizeof(_ty2F) == sizeof(Word)); \ 135 _arg1 = (Word)(_arg1F); \ 136 _arg2 = (Word)(_arg2F); \ 137 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \ 138 (_creqF), \ 139 _arg1,_arg2,0,0,0); \ 140 } while (0) 141 142 #define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, _ty2F,_arg2F) \ 143 do { \ 144 Word _res, _arg1, _arg2; \ 145 assert(sizeof(_ty1F) == sizeof(Word)); \ 146 assert(sizeof(_ty2F) == sizeof(Word)); \ 147 _arg1 = (Word)(_arg1F); \ 148 _arg2 = (Word)(_arg2F); \ 149 VALGRIND_DO_CLIENT_REQUEST(_res, 2, \ 150 (_creqF), \ 151 _arg1,_arg2,0,0,0); \ 152 _resF = _res; \ 153 } while (0) 154 155 #define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \ 156 _ty2F,_arg2F, _ty3F, _arg3F) \ 157 do { \ 158 Word _unused_res, _arg1, _arg2, _arg3; \ 159 assert(sizeof(_ty1F) == sizeof(Word)); \ 160 assert(sizeof(_ty2F) == sizeof(Word)); \ 161 assert(sizeof(_ty3F) == sizeof(Word)); \ 162 _arg1 = (Word)(_arg1F); \ 163 _arg2 = (Word)(_arg2F); \ 164 _arg3 = (Word)(_arg3F); \ 165 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \ 166 (_creqF), \ 167 _arg1,_arg2,_arg3,0,0); \ 168 } while (0) 169 170 #define DO_CREQ_v_WWWW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F,\ 171 _ty3F,_arg3F, _ty4F, _arg4F) \ 172 do { \ 173 Word _unused_res, _arg1, _arg2, _arg3, _arg4; \ 174 assert(sizeof(_ty1F) == sizeof(Word)); \ 175 assert(sizeof(_ty2F) == sizeof(Word)); \ 176 assert(sizeof(_ty3F) == sizeof(Word)); \ 177 assert(sizeof(_ty4F) == sizeof(Word)); \ 178 _arg1 = (Word)(_arg1F); \ 179 _arg2 = (Word)(_arg2F); \ 180 _arg3 = (Word)(_arg3F); \ 181 _arg4 = (Word)(_arg4F); \ 182 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \ 183 (_creqF), \ 184 _arg1,_arg2,_arg3,_arg4,0); \ 185 } while (0) 186 187 188 189 #define DO_PthAPIerror(_fnnameF, _errF) \ 190 do { \ 191 char* _fnname = (char*)(_fnnameF); \ 192 long _err = (long)(int)(_errF); \ 193 char* _errstr = lame_strerror(_err); \ 194 DO_CREQ_v_WWW(TSREQ_PTH_API_ERROR, \ 195 char*,_fnname, \ 196 long,_err, char*,_errstr); \ 197 } while (0) 198 199 static inline void IGNORE_ALL_ACCESSES_BEGIN(void) { 200 DO_CREQ_v_W(TSREQ_IGNORE_ALL_ACCESSES_BEGIN, void*, NULL); 201 } 202 203 static inline void IGNORE_ALL_ACCESSES_END(void) { 204 DO_CREQ_v_W(TSREQ_IGNORE_ALL_ACCESSES_END, void*, NULL); 205 } 206 207 static inline void IGNORE_ALL_SYNC_BEGIN(void) { 208 DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_BEGIN, void*, NULL); 209 } 210 211 static inline void IGNORE_ALL_SYNC_END(void) { 212 DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_END, void*, NULL); 213 } 214 215 static inline void IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(void) { 216 IGNORE_ALL_ACCESSES_BEGIN(); 217 IGNORE_ALL_SYNC_BEGIN(); 218 } 219 220 static inline void IGNORE_ALL_ACCESSES_AND_SYNC_END(void) { 221 IGNORE_ALL_ACCESSES_END(); 222 IGNORE_ALL_SYNC_END(); 223 } 224 225 //-------------- Wrapper for main() -------- {{{1 226 #define MAIN_WRAPPER_DECL \ 227 int I_WRAP_SONAME_FNNAME_ZU(NONE,main) (long argc, char **argv, char **env) 228 229 MAIN_WRAPPER_DECL; 230 MAIN_WRAPPER_DECL { 231 int ret; 232 OrigFn fn; 233 VALGRIND_GET_ORIG_FN(fn); 234 DO_CREQ_v_WW(TSREQ_MAIN_IN, long, argc, char **, argv); 235 CALL_FN_W_WWW(ret, fn, argc, argv, env); 236 DO_CREQ_v_W(TSREQ_MAIN_OUT, void*, ret); 237 return ret; 238 } 239 240 //-------------- MALLOC -------------------- {{{1 241 242 // We ignore memory accesses and sync events inside malloc. 243 // Accesses are ignored so that we don't spend time on them. 244 // Sync events are ignored so that malloc does not create h-b arcs. 245 // Currently, we ignore only Lock/Unlock events, not any other sync events. 246 247 #define WRAP_MALLOC(soname, fnname) \ 248 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n); \ 249 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n) { \ 250 void* ret; \ 251 OrigFn fn;\ 252 VALGRIND_GET_ORIG_FN(fn);\ 253 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 254 CALL_FN_W_W(ret, fn, n); \ 255 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 256 DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n); \ 257 return ret; \ 258 } 259 260 #define WRAP_CALLOC(soname, fnname) \ 261 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n, SizeT c); \ 262 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n, SizeT c) { \ 263 void* ret; \ 264 OrigFn fn;\ 265 VALGRIND_GET_ORIG_FN(fn);\ 266 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 267 CALL_FN_W_WW(ret, fn, n, c); \ 268 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 269 DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n * c); \ 270 return ret; \ 271 } 272 273 #define WRAP_REALLOC(soname, fnname) \ 274 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, SizeT n); \ 275 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, SizeT n) { \ 276 void* ret; \ 277 OrigFn fn;\ 278 VALGRIND_GET_ORIG_FN(fn);\ 279 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 280 CALL_FN_W_WW(ret, fn, ptr, n); \ 281 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 282 DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n); \ 283 return ret; \ 284 } 285 286 #define WRAP_POSIX_MEMALIGN(soname, fnname) \ 287 int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void **ptr, long a, long size);\ 288 int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void **ptr, long a, long size){\ 289 OrigFn fn;\ 290 int ret;\ 291 VALGRIND_GET_ORIG_FN(fn);\ 292 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 293 CALL_FN_W_WWW(ret, fn, ptr, a, size); \ 294 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 295 if (ret == 0) \ 296 DO_CREQ_v_WW(TSREQ_MALLOC, void*, *ptr, long, size); \ 297 return ret; \ 298 } 299 300 #define WRAP_WORKQ_OPS(soname, fnname) \ 301 int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (int options, void* item, \ 302 int priority);\ 303 int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (int options, void* item, \ 304 int priority){\ 305 OrigFn fn;\ 306 int ret;\ 307 VALGRIND_GET_ORIG_FN(fn);\ 308 CALL_FN_W_WWW(ret, fn, options, item, priority); \ 309 /* Trigger only on workq_ops(QUEUE_ADD) */ \ 310 if (options == 1) { \ 311 DO_CREQ_v_W(TSREQ_SIGNAL, void*,item); \ 312 } \ 313 return ret; \ 314 } 315 316 WRAP_WORKQ_OPS(VG_Z_LIBC_SONAME, __workq_ops); 317 318 #ifdef ANDROID 319 #define OFF_T_SIZE 4 320 #else 321 // TODO: this is probably wrong for 32-bit code without -D_FILE_OFFSET_BITS=64 322 #define OFF_T_SIZE 8 323 #endif 324 325 // Hacky workaround for https://bugs.kde.org/show_bug.cgi?id=228471 326 // Used in mmap and lockf wrappers. 327 #if VG_WORDSIZE < OFF_T_SIZE 328 typedef unsigned long long OFF_T; 329 #define CALL_FN_W_5WO_T(ret,fn,p1,p2,p3,p4,p5,off_t_p) CALL_FN_W_7W(ret,fn,\ 330 p1,p2,p3,p4,p5,off_t_p & 0xffffffff, off_t_p >> 32) 331 #define CALL_FN_W_2WO_T(ret,fn,p1,p2,off_t_p) CALL_FN_W_WWWW(ret,fn,\ 332 p1,p2,off_t_p & 0xffffffff, off_t_p >> 32) 333 #else 334 typedef long OFF_T; 335 #define CALL_FN_W_5WO_T(ret,fn,p1,p2,p3,p4,p5,off_t_p) CALL_FN_W_6W(ret,fn,\ 336 p1,p2,p3,p4,p5,off_t_p) 337 #define CALL_FN_W_2WO_T(ret,fn,p1,p2,off_t_p) CALL_FN_W_WWW(ret,fn,\ 338 p1,p2,off_t_p) 339 #endif 340 341 #define WRAP_MMAP(soname, fnname) \ 342 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, long size, long a, \ 343 long b, long c, OFF_T d); \ 344 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, long size, long a, \ 345 long b, long c, OFF_T d){ \ 346 void* ret;\ 347 OrigFn fn;\ 348 VALGRIND_GET_ORIG_FN(fn);\ 349 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 350 CALL_FN_W_5WO_T(ret, fn, ptr, size, a, b, c, d); \ 351 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 352 if (ret != (void*)-1) { \ 353 DO_CREQ_v_WW(TSREQ_MMAP, void*, ret, long, size); \ 354 } \ 355 return ret; \ 356 } 357 358 #define WRAP_MUNMAP(soname, fnname) \ 359 int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, size_t size); \ 360 int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, size_t size){ \ 361 int ret;\ 362 OrigFn fn;\ 363 VALGRIND_GET_ORIG_FN(fn);\ 364 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 365 CALL_FN_W_WW(ret, fn, ptr, size); \ 366 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 367 if (ret == 0) { \ 368 DO_CREQ_v_WW(TSREQ_MUNMAP, void*, ptr, size_t, size); \ 369 } \ 370 return ret; \ 371 } 372 373 #define WRAP_ZONE_MALLOC(soname, fnname) \ 374 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n); \ 375 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n) { \ 376 void* ret; \ 377 OrigFn fn;\ 378 VALGRIND_GET_ORIG_FN(fn);\ 379 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 380 CALL_FN_W_WW(ret, fn, zone, n); \ 381 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 382 DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n); \ 383 return ret; \ 384 } 385 386 #define WRAP_ZONE_CALLOC(soname, fnname) \ 387 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n, SizeT c); \ 388 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n, SizeT c) { \ 389 void* ret; \ 390 OrigFn fn;\ 391 VALGRIND_GET_ORIG_FN(fn);\ 392 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 393 CALL_FN_W_WWW(ret, fn, zone, n, c); \ 394 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 395 DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n * c); \ 396 return ret; \ 397 } 398 399 #define WRAP_ZONE_REALLOC(soname, fnname) \ 400 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, void *ptr, SizeT n); \ 401 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, void *ptr, SizeT n) { \ 402 void* ret; \ 403 OrigFn fn;\ 404 VALGRIND_GET_ORIG_FN(fn);\ 405 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 406 CALL_FN_W_WWW(ret, fn, zone, ptr, n); \ 407 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 408 DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n); \ 409 return ret; \ 410 } 411 412 413 WRAP_ZONE_MALLOC(VG_Z_LIBC_SONAME, malloc_zone_malloc); 414 WRAP_ZONE_CALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc); 415 WRAP_ZONE_REALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc); 416 417 WRAP_MALLOC(VG_Z_LIBC_SONAME, malloc); 418 WRAP_MALLOC(NONE, malloc); 419 420 WRAP_MALLOC(VG_Z_LIBC_SONAME, valloc); 421 WRAP_MALLOC(NONE, valloc); 422 WRAP_MALLOC(VG_Z_LIBC_SONAME, pvalloc); 423 WRAP_MALLOC(NONE, pvalloc); 424 425 WRAP_MALLOC(NONE, _Znam); 426 WRAP_MALLOC(NONE, _Znwm); 427 WRAP_MALLOC(NONE, _Znaj); 428 WRAP_MALLOC(NONE, _Znwj); 429 WRAP_MALLOC(NONE, _ZnamRKSt9nothrow_t); 430 WRAP_MALLOC(NONE, _ZnwmRKSt9nothrow_t); 431 WRAP_MALLOC(NONE, _ZnajRKSt9nothrow_t); 432 WRAP_MALLOC(NONE, _ZnwjRKSt9nothrow_t); 433 // same for libstdc++. 434 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znam); 435 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znwm); 436 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znaj); 437 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znwj); 438 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t); 439 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t); 440 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t); 441 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t); 442 443 444 WRAP_CALLOC(VG_Z_LIBC_SONAME, calloc); 445 WRAP_CALLOC(NONE, calloc); 446 447 WRAP_REALLOC(VG_Z_LIBC_SONAME, realloc); // TODO: handle free inside realloc 448 WRAP_REALLOC(NONE, realloc); // TODO: handle free inside realloc 449 WRAP_REALLOC(VG_Z_LIBC_SONAME, memalign); 450 WRAP_REALLOC(NONE, memalign); 451 WRAP_POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign); 452 WRAP_POSIX_MEMALIGN(NONE, posix_memalign); 453 454 WRAP_MMAP(VG_Z_LIBC_SONAME, mmap); 455 WRAP_MMAP(NONE, mmap); 456 457 WRAP_MUNMAP(VG_Z_LIBC_SONAME, munmap); 458 WRAP_MUNMAP(NONE, munmap); 459 460 #define WRAP_FREE(soname, fnname) \ 461 void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr); \ 462 void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr) { \ 463 OrigFn fn;\ 464 VALGRIND_GET_ORIG_FN(fn);\ 465 DO_CREQ_v_W(TSREQ_FREE, void*, ptr); \ 466 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 467 CALL_FN_v_W(fn, ptr); \ 468 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 469 } 470 471 472 #define WRAP_FREE_ZZ(soname, fnname) \ 473 void I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) (void *ptr); \ 474 void I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) (void *ptr) { \ 475 OrigFn fn;\ 476 VALGRIND_GET_ORIG_FN(fn);\ 477 DO_CREQ_v_W(TSREQ_FREE, void*, ptr); \ 478 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 479 CALL_FN_v_W(fn, ptr); \ 480 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 481 } 482 483 484 #define WRAP_ZONE_FREE(soname, fnname) \ 485 void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *zone, void *ptr); \ 486 void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *zone, void *ptr) { \ 487 OrigFn fn;\ 488 VALGRIND_GET_ORIG_FN(fn);\ 489 DO_CREQ_v_W(TSREQ_FREE, void*, ptr); \ 490 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \ 491 CALL_FN_v_WW(fn, zone, ptr); \ 492 IGNORE_ALL_ACCESSES_AND_SYNC_END(); \ 493 } 494 495 WRAP_FREE(VG_Z_LIBC_SONAME, free); 496 WRAP_ZONE_FREE(VG_Z_LIBC_SONAME, malloc_zone_free); 497 498 WRAP_FREE(NONE, free); 499 500 WRAP_FREE(NONE, _ZdlPv); 501 WRAP_FREE(NONE, _ZdaPv); 502 WRAP_FREE(NONE, _ZdlPvRKSt9nothrow_t); 503 WRAP_FREE(NONE, _ZdaPvRKSt9nothrow_t); 504 // same for libstdc++ 505 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv); 506 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv); 507 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t); 508 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t); 509 510 // operator delete 511 WRAP_FREE_ZZ(NONE, operatorZsdeleteZa); 512 513 514 /* Handle tcmalloc (http://code.google.com/p/google-perftools/) */ 515 516 /* tc_ functions (used when tcmalloc is running in release mode) */ 517 WRAP_MALLOC(NONE,tc_malloc); 518 WRAP_MALLOC(NONE,tc_new); 519 WRAP_MALLOC(NONE,tc_new_nothrow); 520 WRAP_MALLOC(NONE,tc_newarray); 521 WRAP_MALLOC(NONE,tc_newarray_nothrow); 522 WRAP_FREE(NONE,tc_free); 523 WRAP_FREE(NONE,tc_cfree); 524 WRAP_FREE(NONE,tc_delete); 525 WRAP_FREE(NONE,tc_delete_nothrow); 526 WRAP_FREE(NONE,tc_deletearray); 527 WRAP_FREE(NONE,tc_deletearray_nothrow); 528 WRAP_CALLOC(NONE,tc_calloc); 529 WRAP_REALLOC(NONE,tc_realloc); 530 WRAP_MALLOC(NONE,tc_valloc); 531 WRAP_POSIX_MEMALIGN(NONE,tc_memalign); 532 WRAP_POSIX_MEMALIGN(NONE,tc_posix_memalign); 533 534 535 536 //------------ Wrappers for stdio functions --------- 537 /* These functions have internal synchronization that we don't handle and get 538 lots of false positives. To fix this, we wrap these functions, touch their 539 arguments, and pass them through to the original function, ignoring all 540 memory accesses inside it. */ 541 542 size_t I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, fwrite) (const void *ptr, size_t size, size_t nmemb, void* stream); 543 size_t I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, fwrite) (const void *ptr, size_t size, size_t nmemb, void* stream) { 544 size_t ret; 545 OrigFn fn; 546 ReadMemory(ptr, size * nmemb); 547 VALGRIND_GET_ORIG_FN(fn); 548 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); 549 CALL_FN_W_WWWW(ret, fn, ptr, size, nmemb, stream); 550 IGNORE_ALL_ACCESSES_AND_SYNC_END(); 551 return ret; 552 } 553 554 int I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, puts) (const char *s); 555 int I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, puts) (const char *s) { 556 int ret; 557 OrigFn fn; 558 ReadString(s); 559 VALGRIND_GET_ORIG_FN(fn); 560 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); 561 CALL_FN_W_W(ret, fn, s); 562 IGNORE_ALL_ACCESSES_AND_SYNC_END(); 563 return ret; 564 } 565 566 567 //-------------- PTHREADS -------------------- {{{1 568 /* A lame version of strerror which doesn't use the real libc 569 strerror_r, since using the latter just generates endless more 570 threading errors (glibc goes off and does tons of crap w.r.t. 571 locales etc) */ 572 static char* lame_strerror ( long err ) 573 { switch (err) { 574 case EPERM: return "EPERM: Operation not permitted"; 575 case ENOENT: return "ENOENT: No such file or directory"; 576 case ESRCH: return "ESRCH: No such process"; 577 case EINTR: return "EINTR: Interrupted system call"; 578 case EBADF: return "EBADF: Bad file number"; 579 case EAGAIN: return "EAGAIN: Try again"; 580 case ENOMEM: return "ENOMEM: Out of memory"; 581 case EACCES: return "EACCES: Permission denied"; 582 case EFAULT: return "EFAULT: Bad address"; 583 case EEXIST: return "EEXIST: File exists"; 584 case EINVAL: return "EINVAL: Invalid argument"; 585 case EMFILE: return "EMFILE: Too many open files"; 586 case ENOSYS: return "ENOSYS: Function not implemented"; 587 case EOVERFLOW: return "EOVERFLOW: Value too large " 588 "for defined data type"; 589 case EBUSY: return "EBUSY: Device or resource busy"; 590 case ETIMEDOUT: return "ETIMEDOUT: Connection timed out"; 591 case EDEADLK: return "EDEADLK: Resource deadlock would occur"; 592 case EOPNOTSUPP: return "EOPNOTSUPP: Operation not supported on " 593 "transport endpoint"; /* honest, guv */ 594 default: return "tc_intercepts.c: lame_strerror(): " 595 "unhandled case -- please fix me!"; 596 } 597 } 598 599 600 // libpthread sentry functions. 601 // Darwin implementations of several libpthread functions call other functions 602 // that are intercepted by ThreadSanitizer as well. To avoid reacting on those 603 // functions twice the status of each Valgrind thread is stored in the 604 // tid_inside_pthread_lib array and all the client requests from the inner 605 // pthread functions are ignored. 606 607 static int tid_inside_pthread_lib[VG_N_THREADS]; 608 609 // A pthread_*() function must call pthread_lib_enter() if its implementation 610 // calls or is called by another pthread_*() function. The function that 611 // called pthread_lib_enter() should perform client requests to ThreadSanitizer 612 // iff the return value of pthread_lib_enter() is equal to 1. 613 static int pthread_lib_enter(void) { 614 int ret = 1, tid; 615 IGNORE_ALL_ACCESSES_BEGIN(); 616 tid = VALGRIND_VG_THREAD_ID(); 617 if (tid_inside_pthread_lib[tid]++) { 618 ret = 0; 619 } else { 620 ret = 1; 621 } 622 IGNORE_ALL_ACCESSES_END(); 623 return ret; 624 } 625 626 // A pthread_*() function must call pthread_lib_exit() iff it has called 627 // pthread_lib_enter(). 628 static void pthread_lib_exit(void) { 629 int tid; 630 IGNORE_ALL_ACCESSES_BEGIN(); 631 tid = VALGRIND_VG_THREAD_ID(); 632 tid_inside_pthread_lib[tid]--; 633 IGNORE_ALL_ACCESSES_END(); 634 } 635 636 /*----------------------------------------------------------------*/ 637 /*--- pthread_create, pthread_join, pthread_exit ---*/ 638 /*----------------------------------------------------------------*/ 639 640 static void* ThreadSanitizerStartThread ( void* xargsV ) 641 { 642 volatile Word volatile* xargs = (volatile Word volatile*) xargsV; 643 void*(*fn)(void*) = (void*(*)(void*))xargs[0]; 644 void* arg = (void*)xargs[1]; 645 pthread_t me = pthread_self(); 646 size_t stacksize = 0; 647 void *stackaddr = NULL; 648 pthread_attr_t attr; 649 650 /* Tell the tool what my pthread_t is. */ 651 DO_CREQ_v_W(TSREQ_SET_MY_PTHREAD_T, pthread_t,me); 652 #ifdef VGO_darwin 653 /* Tell the tool what my stack size and stack top are. 654 This is Darwin-specific and works as long as ThreadSanitizerStartThread 655 is used for pthreads only. 656 */ 657 stacksize = pthread_get_stacksize_np(me); 658 stackaddr = pthread_get_stackaddr_np(me); 659 DO_CREQ_v_WW(TSREQ_SET_STACKTOP_STACKSIZE, void*, stackaddr, 660 size_t, stacksize); 661 #else 662 if (pthread_getattr_np(pthread_self(), &attr) == 0) { 663 pthread_attr_getstack(&attr, &stackaddr, &stacksize); 664 pthread_attr_destroy(&attr); 665 DO_CREQ_v_WW(TSREQ_SET_STACKTOP_STACKSIZE, 666 void*, (char*)stackaddr + stacksize, 667 size_t, stacksize); 668 } else { 669 /* Let the tool guess where the stack starts. */ 670 DO_CREQ_v_W(TSREQ_THR_STACK_TOP, void*, &stacksize); 671 } 672 #endif 673 /* allow the parent to proceed. We can't let it proceed until 674 we're ready because (1) we need to make sure it doesn't exit and 675 hence deallocate xargs[] while we still need it, and (2) we 676 don't want either parent nor child to proceed until the tool has 677 been notified of the child's pthread_t. */ 678 xargs[2] = 0; 679 /* Now we can no longer safely use xargs[]. */ 680 return (void*) fn( (void*)arg ); 681 } 682 683 static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr, 684 void *(*start) (void *), void *arg) 685 { 686 int ret; 687 OrigFn fn; 688 volatile Word xargs[3]; 689 690 VALGRIND_GET_ORIG_FN(fn); 691 if (TRACE_PTH_FNS) { 692 fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr); 693 } 694 xargs[0] = (Word)start; 695 xargs[1] = (Word)arg; 696 xargs[2] = 1; /* serves as a spinlock -- sigh */ 697 698 IGNORE_ALL_ACCESSES_BEGIN(); 699 CALL_FN_W_WWWW(ret, fn, thread,attr,ThreadSanitizerStartThread,&xargs[0]); 700 IGNORE_ALL_ACCESSES_END(); 701 702 if (ret == 0) { 703 /* we have to wait for the child to notify the tool of its 704 pthread_t before continuing */ 705 while (xargs[2] != 0) { 706 /* Do nothing. We need to spin until the child writes to 707 xargs[2]. However, that can lead to starvation in the 708 child and very long delays (eg, tc19_shadowmem on 709 ppc64-linux Fedora Core 6). So yield the cpu if we can, 710 to let the child run at the earliest available 711 opportunity. */ 712 sched_yield(); 713 } 714 } else { 715 DO_PthAPIerror( "pthread_create", ret ); 716 } 717 718 if (TRACE_PTH_FNS) { 719 fprintf(stderr, " :: pth_create -> %d >>\n", ret); 720 } 721 return ret; 722 } 723 724 PTH_FUNC(int, pthreadZucreate, // pthread_create (Darwin) 725 pthread_t *thread, const pthread_attr_t *attr, 726 void *(*start) (void *), void *arg) { 727 return pthread_create_WRK(thread, attr, start, arg); 728 } 729 PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@* (Linux) 730 pthread_t *thread, const pthread_attr_t *attr, 731 void *(*start) (void *), void *arg) { 732 return pthread_create_WRK(thread, attr, start, arg); 733 } 734 735 // pthread_join 736 static int pthread_join_WRK(pthread_t thread, void** value_pointer) 737 { 738 int ret; 739 OrigFn fn; 740 VALGRIND_GET_ORIG_FN(fn); 741 if (TRACE_PTH_FNS) { 742 fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr); 743 } 744 745 CALL_FN_W_WW(ret, fn, thread,value_pointer); 746 747 /* At least with NPTL as the thread library, this is safe because 748 it is guaranteed (by NPTL) that the joiner will completely gone 749 before pthread_join (the original) returns. See email below.*/ 750 if (ret == 0 /*success*/) { 751 DO_CREQ_v_W(TSREQ_PTHREAD_JOIN_POST, pthread_t,thread); 752 } else { 753 DO_PthAPIerror( "pthread_join", ret ); 754 } 755 756 if (TRACE_PTH_FNS) { 757 fprintf(stderr, " :: pth_join -> %d >>\n", ret); 758 } 759 return ret; 760 } 761 762 PTH_FUNC(int, pthreadZujoin, // pthread_join (Linux) 763 pthread_t thread, void** value_pointer) 764 { 765 return pthread_join_WRK(thread, value_pointer); 766 } 767 768 PTH_FUNC(int, pthreadZujoin$Za, // pthread_join$* (Darwin) 769 pthread_t thread, void** value_pointer) 770 { 771 return pthread_join_WRK(thread, value_pointer); 772 } 773 774 775 776 /* Behaviour of pthread_join on NPTL: 777 778 Me: 779 I have a question re the NPTL pthread_join implementation. 780 781 Suppose I am the thread 'stayer'. 782 783 If I call pthread_join(quitter), is it guaranteed that the 784 thread 'quitter' has really exited before pthread_join returns? 785 786 IOW, is it guaranteed that 'quitter' will not execute any further 787 instructions after pthread_join returns? 788 789 I believe this is true based on the following analysis of 790 glibc-2.5 sources. However am not 100% sure and would appreciate 791 confirmation. 792 793 'quitter' will be running start_thread() in nptl/pthread_create.c 794 795 The last action of start_thread() is to exit via 796 __exit_thread_inline(0), which simply does sys_exit 797 (nptl/pthread_create.c:403) 798 799 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid) 800 (call at nptl/pthread_join.c:89) 801 802 As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536, 803 lll_wait_tid will not return until kernel notifies via futex 804 wakeup that 'quitter' has terminated. 805 806 Hence pthread_join cannot return until 'quitter' really has 807 completely disappeared. 808 809 Drepper: 810 > As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536, 811 > lll_wait_tid will not return until kernel notifies via futex 812 > wakeup that 'quitter' has terminated. 813 That's the key. The kernel resets the TID field after the thread is 814 done. No way the joiner can return before the thread is gone. 815 */ 816 817 #ifdef ANDROID 818 // Android-specific part. Ignore some internal synchronization in bionic. 819 PTH_FUNC(int, pthreadZuexit, void* retval) // pthread_exit (Android) 820 { 821 int ret; 822 OrigFn fn; 823 VALGRIND_GET_ORIG_FN(fn); 824 IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); 825 CALL_FN_W_W(ret, fn, retval); 826 IGNORE_ALL_ACCESSES_AND_SYNC_END(); 827 return ret; 828 } 829 #endif 830 831 832 /*----------------------------------------------------------------*/ 833 /*--- pthread_mutex_t functions ---*/ 834 /*----------------------------------------------------------------*/ 835 836 /* Handled: pthread_mutex_init pthread_mutex_destroy 837 pthread_mutex_lock 838 pthread_mutex_trylock 839 pthread_mutex_timedlock 840 pthread_mutex_unlock 841 842 pthread_spin_init pthread_spin_destroy 843 pthread_spin_lock 844 pthread_spin_trylock 845 pthread_spin_unlock 846 */ 847 848 // pthread_mutex_init 849 PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init 850 pthread_mutex_t *mutex, 851 pthread_mutexattr_t* attr) 852 { 853 int ret; 854 long mbRec; 855 OrigFn fn; 856 VALGRIND_GET_ORIG_FN(fn); 857 if (TRACE_PTH_FNS) { 858 fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr); 859 } 860 861 mbRec = 0; 862 if (attr) { 863 int ty, zzz; 864 zzz = pthread_mutexattr_gettype(attr, &ty); 865 if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE) 866 mbRec = 1; 867 } 868 869 CALL_FN_W_WW(ret, fn, mutex,attr); 870 871 if (ret == 0 /*success*/) { 872 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_CREATE_POST, 873 pthread_mutex_t*,mutex, long,mbRec); 874 } else { 875 DO_PthAPIerror( "pthread_mutex_init", ret ); 876 } 877 878 if (TRACE_PTH_FNS) { 879 fprintf(stderr, " :: mxinit -> %d >>\n", ret); 880 } 881 return ret; 882 } 883 884 885 // pthread_mutex_destroy 886 PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy 887 pthread_mutex_t *mutex) 888 { 889 int ret; 890 OrigFn fn; 891 VALGRIND_GET_ORIG_FN(fn); 892 if (TRACE_PTH_FNS) { 893 fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr); 894 } 895 896 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, 897 pthread_mutex_t*,mutex); 898 899 CALL_FN_W_W(ret, fn, mutex); 900 901 if (ret != 0) { 902 DO_PthAPIerror( "pthread_mutex_destroy", ret ); 903 } 904 905 if (TRACE_PTH_FNS) { 906 fprintf(stderr, " :: mxdestroy -> %d >>\n", ret); 907 } 908 return ret; 909 } 910 911 912 // pthread_mutex_lock 913 PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock 914 pthread_mutex_t *mutex) 915 { 916 int ret; 917 OrigFn fn; 918 int is_outermost; 919 VALGRIND_GET_ORIG_FN(fn); 920 if (TRACE_PTH_FNS) { 921 fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr); 922 } 923 924 is_outermost = pthread_lib_enter(); 925 926 CALL_FN_W_W(ret, fn, mutex); 927 928 /* There's a hole here: libpthread now knows the lock is locked, 929 but the tool doesn't, so some other thread could run and detect 930 that the lock has been acquired by someone (this thread). Does 931 this matter? Not sure, but I don't think so. */ 932 933 if (is_outermost) { 934 if ((ret == 0 /*success*/)) { 935 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 936 pthread_mutex_t*,mutex, long, 1); 937 } else { 938 DO_PthAPIerror( "pthread_mutex_lock", ret ); 939 } 940 } 941 942 if (TRACE_PTH_FNS) { 943 fprintf(stderr, " :: mxlock -> %d >>\n", ret); 944 } 945 pthread_lib_exit(); 946 return ret; 947 } 948 949 950 // pthread_mutex_trylock. The handling needed here is very similar 951 // to that for pthread_mutex_lock, except that we need to tell 952 // the pre-lock creq that this is a trylock-style operation, and 953 // therefore not to complain if the lock is nonrecursive and 954 // already locked by this thread -- because then it'll just fail 955 // immediately with EBUSY. 956 static int pthread_mutex_trylock_WRK(pthread_mutex_t *mutex) 957 { 958 int ret; 959 OrigFn fn; 960 VALGRIND_GET_ORIG_FN(fn); 961 if (TRACE_PTH_FNS) { 962 fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr); 963 } 964 965 CALL_FN_W_W(ret, fn, mutex); 966 967 /* There's a hole here: libpthread now knows the lock is locked, 968 but the tool doesn't, so some other thread could run and detect 969 that the lock has been acquired by someone (this thread). Does 970 this matter? Not sure, but I don't think so. */ 971 972 if (ret == 0 /*success*/) { 973 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 974 pthread_mutex_t*,mutex, long, 1); 975 } else { 976 if (ret != EBUSY) 977 DO_PthAPIerror( "pthread_mutex_trylock", ret ); 978 } 979 980 if (TRACE_PTH_FNS) { 981 fprintf(stderr, " :: mxtrylock -> %d >>\n", ret); 982 } 983 return ret; 984 } 985 986 PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock 987 pthread_mutex_t *mutex) 988 { 989 return pthread_mutex_trylock_WRK(mutex); 990 } 991 992 993 // pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock. 994 // Not implemented in Darwin pthreads. 995 PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock 996 pthread_mutex_t *mutex, 997 void* timeout) 998 { 999 int ret; 1000 OrigFn fn; 1001 VALGRIND_GET_ORIG_FN(fn); 1002 if (TRACE_PTH_FNS) { 1003 fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout); 1004 fflush(stderr); 1005 } 1006 1007 CALL_FN_W_WW(ret, fn, mutex,timeout); 1008 1009 /* There's a hole here: libpthread now knows the lock is locked, 1010 but the tool doesn't, so some other thread could run and detect 1011 that the lock has been acquired by someone (this thread). Does 1012 this matter? Not sure, but I don't think so. */ 1013 1014 if (ret == 0 /*success*/) { 1015 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 1016 pthread_mutex_t*,mutex, long, 1); 1017 } else { 1018 if (ret != ETIMEDOUT) 1019 DO_PthAPIerror( "pthread_mutex_timedlock", ret ); 1020 } 1021 1022 if (TRACE_PTH_FNS) { 1023 fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret); 1024 } 1025 return ret; 1026 } 1027 1028 1029 // pthread_mutex_unlock 1030 PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock 1031 pthread_mutex_t *mutex) 1032 { 1033 int ret; 1034 OrigFn fn; 1035 VALGRIND_GET_ORIG_FN(fn); 1036 1037 if (TRACE_PTH_FNS) { 1038 fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr); 1039 } 1040 1041 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, 1042 pthread_mutex_t*,mutex); 1043 1044 CALL_FN_W_W(ret, fn, mutex); 1045 1046 if (ret != 0 /*error*/) { 1047 DO_PthAPIerror( "pthread_mutex_unlock", ret ); 1048 } 1049 1050 if (TRACE_PTH_FNS) { 1051 fprintf(stderr, " mxunlk -> %d >>\n", ret); 1052 } 1053 return ret; 1054 } 1055 1056 // pthread_spin_init 1057 PTH_FUNC(int, pthreadZuspinZuinit, void *lock, int pshared) { 1058 int ret; 1059 OrigFn fn; 1060 const char *func = "pthread_spin_init"; 1061 VALGRIND_GET_ORIG_FN(fn); 1062 if (TRACE_PTH_FNS) { 1063 fprintf(stderr, "<< %s %p", func, lock); 1064 } 1065 CALL_FN_W_WW(ret, fn, lock, pshared); 1066 if (ret == 0) { 1067 DO_CREQ_v_W(TSREQ_PTHREAD_SPIN_LOCK_INIT_OR_UNLOCK, void *, lock); 1068 } 1069 if (TRACE_PTH_FNS) { 1070 fprintf(stderr, " -- %p >>\n", lock); 1071 } 1072 return ret; 1073 } 1074 1075 // pthread_spin_destroy 1076 PTH_FUNC(int, pthreadZuspinZudestroy, void *lock) { 1077 int ret; 1078 OrigFn fn; 1079 const char *func = "pthread_spin_destroy"; 1080 VALGRIND_GET_ORIG_FN(fn); 1081 if (TRACE_PTH_FNS) { 1082 fprintf(stderr, "<< %s %p", func, lock); 1083 } 1084 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, void*, lock); 1085 CALL_FN_W_W(ret, fn, lock); 1086 if (TRACE_PTH_FNS) { 1087 fprintf(stderr, " -- %p >>\n", lock); 1088 } 1089 return ret; 1090 } 1091 1092 // pthread_spin_lock 1093 PTH_FUNC(int, pthreadZuspinZulock, void *lock) { 1094 int ret; 1095 OrigFn fn; 1096 const char *func = "pthread_spin_lock"; 1097 VALGRIND_GET_ORIG_FN(fn); 1098 if (TRACE_PTH_FNS) { 1099 fprintf(stderr, "<< %s %p", func, lock); 1100 } 1101 CALL_FN_W_W(ret, fn, lock); 1102 if (ret == 0) { 1103 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *, lock, 1104 long, 1 /*is_w*/); 1105 } 1106 if (TRACE_PTH_FNS) { 1107 fprintf(stderr, " -- %p >>\n", lock); 1108 } 1109 return ret; 1110 } 1111 1112 // pthread_spin_trylock 1113 PTH_FUNC(int, pthreadZuspinZutrylock, void *lock) { 1114 int ret; 1115 OrigFn fn; 1116 const char *func = "pthread_spin_trylock"; 1117 VALGRIND_GET_ORIG_FN(fn); 1118 if (TRACE_PTH_FNS) { 1119 fprintf(stderr, "<< %s %p", func, lock); 1120 } 1121 CALL_FN_W_W(ret, fn, lock); 1122 if (ret == 0) { 1123 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *, lock, 1124 long, 1 /*is_w*/); 1125 } 1126 if (TRACE_PTH_FNS) { 1127 fprintf(stderr, " -- %p >>\n", lock); 1128 } 1129 return ret; 1130 } 1131 1132 // pthread_spin_unlock 1133 PTH_FUNC(int, pthreadZuspinZuunlock, void *lock) { 1134 int ret; 1135 OrigFn fn; 1136 const char *func = "pthread_spin_unlock"; 1137 VALGRIND_GET_ORIG_FN(fn); 1138 if (TRACE_PTH_FNS) { 1139 fprintf(stderr, "<< %s %p", func, lock); 1140 } 1141 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void*, lock); 1142 CALL_FN_W_W(ret, fn, lock); 1143 if (TRACE_PTH_FNS) { 1144 fprintf(stderr, " -- %p >>\n", lock); 1145 } 1146 return ret; 1147 } 1148 1149 1150 /*----------------------------------------------------------------*/ 1151 /*--- pthread_cond_t functions ---*/ 1152 /*----------------------------------------------------------------*/ 1153 1154 /* Handled: pthread_cond_wait pthread_cond_timedwait 1155 pthread_cond_signal pthread_cond_broadcast 1156 1157 Unhandled: pthread_cond_init pthread_cond_destroy 1158 -- are these important? 1159 */ 1160 1161 // pthread_cond_wait 1162 static int pthread_cond_wait_WRK(pthread_cond_t* cond, pthread_mutex_t* mutex) 1163 { 1164 int ret; 1165 OrigFn fn; 1166 1167 int is_outermost = pthread_lib_enter(); 1168 VALGRIND_GET_ORIG_FN(fn); 1169 1170 if (TRACE_PTH_FNS) { 1171 fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex); 1172 fflush(stderr); 1173 } 1174 if (is_outermost) { 1175 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, pthread_mutex_t*,mutex); 1176 } 1177 1178 CALL_FN_W_WW(ret, fn, cond,mutex); 1179 1180 if (is_outermost) { 1181 DO_CREQ_v_W(TSREQ_WAIT, void *,cond); 1182 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *, mutex, 1183 long, 1 /*is_w*/); 1184 } 1185 1186 if (ret != 0) { 1187 DO_PthAPIerror( "pthread_cond_wait", ret ); 1188 } 1189 1190 if (TRACE_PTH_FNS) { 1191 fprintf(stderr, " cowait -> %d >>\n", ret); 1192 } 1193 1194 pthread_lib_exit(); 1195 1196 return ret; 1197 } 1198 1199 PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@* 1200 pthread_cond_t* cond, pthread_mutex_t* mutex) 1201 { 1202 return pthread_cond_wait_WRK(cond, mutex); 1203 } 1204 1205 PTH_FUNC(int, pthreadZucondZuwait$Za, // pthread_cond_wait$* 1206 pthread_cond_t* cond, pthread_mutex_t* mutex) 1207 { 1208 return pthread_cond_wait_WRK(cond, mutex); 1209 } 1210 1211 1212 // pthread_cond_timedwait 1213 static int pthread_cond_timedwait_WRK(pthread_cond_t* cond, 1214 pthread_mutex_t* mutex, 1215 struct timespec* abstime) 1216 { 1217 int ret; 1218 OrigFn fn; 1219 int is_outermost = pthread_lib_enter(); 1220 VALGRIND_GET_ORIG_FN(fn); 1221 1222 if (TRACE_PTH_FNS) { 1223 fprintf(stderr, "<< pthread_cond_timedwait %p %p %p", 1224 cond, mutex, abstime); 1225 fflush(stderr); 1226 } 1227 1228 /* Tell the tool a cond-wait is about to happen, so it can check 1229 for bogus argument values. In return it tells us whether it 1230 thinks the mutex is valid or not. */ 1231 if (is_outermost) { 1232 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void *,mutex); 1233 } 1234 1235 1236 CALL_FN_W_WWW(ret, fn, cond,mutex,abstime); 1237 1238 if (is_outermost) { 1239 if (ret == 0) { 1240 DO_CREQ_v_W(TSREQ_WAIT, void *, cond); 1241 } 1242 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *,mutex, 1243 long, 1 /*is_w*/); 1244 } 1245 1246 if (ret != 0 && ret != ETIMEDOUT) { 1247 DO_PthAPIerror( "pthread_cond_timedwait", ret ); 1248 } 1249 1250 if (TRACE_PTH_FNS) { 1251 fprintf(stderr, " cotimedwait -> %d >>\n", ret); 1252 } 1253 1254 pthread_lib_exit(); 1255 return ret; 1256 } 1257 1258 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@* 1259 pthread_cond_t* cond, pthread_mutex_t* mutex, 1260 struct timespec* abstime) 1261 { 1262 return pthread_cond_timedwait_WRK(cond, mutex, abstime); 1263 } 1264 1265 PTH_FUNC(int, pthreadZucondZutimedwait$Za, // pthread_cond_timedwait$* 1266 pthread_cond_t* cond, pthread_mutex_t* mutex, 1267 struct timespec* abstime) 1268 { 1269 return pthread_cond_timedwait_WRK(cond, mutex, abstime); 1270 } 1271 1272 PTH_FUNC(int, pthreadZucondZutimedwaitZurelativeZunp, // pthread_cond_timedwait_relative_np 1273 pthread_cond_t* cond, pthread_mutex_t* mutex, 1274 struct timespec* abstime) 1275 { 1276 return pthread_cond_timedwait_WRK(cond, mutex, abstime); 1277 } 1278 1279 1280 // pthread_cond_signal 1281 static int pthread_cond_signal_WRK(pthread_cond_t* cond) 1282 { 1283 int ret; 1284 OrigFn fn; 1285 VALGRIND_GET_ORIG_FN(fn); 1286 1287 if (TRACE_PTH_FNS) { 1288 fprintf(stderr, "<< pthread_cond_signal %p", cond); 1289 fflush(stderr); 1290 } 1291 1292 DO_CREQ_v_W(TSREQ_SIGNAL, 1293 pthread_cond_t*,cond); 1294 1295 CALL_FN_W_W(ret, fn, cond); 1296 1297 if (ret != 0) { 1298 DO_PthAPIerror( "pthread_cond_signal", ret ); 1299 } 1300 1301 if (TRACE_PTH_FNS) { 1302 fprintf(stderr, " cosig -> %d >>\n", ret); 1303 } 1304 1305 return ret; 1306 } 1307 1308 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal 1309 pthread_cond_t* cond) 1310 { 1311 return pthread_cond_signal_WRK(cond); 1312 } 1313 1314 PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@* 1315 pthread_cond_t* cond) 1316 { 1317 return pthread_cond_signal_WRK(cond); 1318 } 1319 1320 // pthread_cond_broadcast 1321 // Note, this is pretty much identical, from a dependency-graph 1322 // point of view, with cond_signal, so the code is duplicated. 1323 // Maybe it should be commoned up. 1324 static int pthread_cond_broadcast_WRK(pthread_cond_t* cond) 1325 { 1326 int ret; 1327 OrigFn fn; 1328 pthread_lib_enter(); 1329 VALGRIND_GET_ORIG_FN(fn); 1330 1331 if (TRACE_PTH_FNS) { 1332 fprintf(stderr, "<< pthread_broadcast_signal %p", cond); 1333 fflush(stderr); 1334 } 1335 1336 DO_CREQ_v_W(TSREQ_SIGNAL, 1337 pthread_cond_t*,cond); 1338 1339 CALL_FN_W_W(ret, fn, cond); 1340 1341 if (ret != 0) { 1342 DO_PthAPIerror( "pthread_cond_broadcast", ret ); 1343 } 1344 1345 if (TRACE_PTH_FNS) { 1346 fprintf(stderr, " cobro -> %d >>\n", ret); 1347 } 1348 1349 pthread_lib_exit(); 1350 return ret; 1351 } 1352 1353 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast 1354 pthread_cond_t* cond) 1355 { 1356 return pthread_cond_broadcast_WRK(cond); 1357 } 1358 1359 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@* 1360 pthread_cond_t* cond) 1361 { 1362 return pthread_cond_broadcast_WRK(cond); 1363 } 1364 1365 static void do_wait(void *cv) { 1366 DO_CREQ_v_W(TSREQ_WAIT, void *, cv); 1367 } 1368 1369 /*----------------------------------------------------------------*/ 1370 /*--- pthread_barrier_t functions ---*/ 1371 /*----------------------------------------------------------------*/ 1372 #if defined(VGO_darwin) || defined(ANDROID) 1373 typedef void pthread_barrier_t; 1374 #endif 1375 // pthread_barrier_wait 1376 static int pthread_barrier_wait_WRK(pthread_barrier_t* b) 1377 { 1378 int ret; 1379 OrigFn fn; 1380 VALGRIND_GET_ORIG_FN(fn); 1381 1382 if (TRACE_PTH_FNS) { 1383 fprintf(stderr, "<< pthread_barrier_wait %p", b); 1384 fflush(stderr); 1385 } 1386 1387 DO_CREQ_v_W(TSREQ_CYCLIC_BARRIER_WAIT_BEFORE, void*,b); 1388 CALL_FN_W_W(ret, fn, b); 1389 DO_CREQ_v_W(TSREQ_CYCLIC_BARRIER_WAIT_AFTER, void*,b); 1390 1391 // FIXME: handle ret 1392 if (TRACE_PTH_FNS) { 1393 fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret); 1394 } 1395 1396 return ret; 1397 } 1398 1399 PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait 1400 pthread_barrier_t* b) 1401 { 1402 return pthread_barrier_wait_WRK(b); 1403 } 1404 1405 // pthread_barrier_init 1406 PTH_FUNC(int, pthreadZubarrierZuinit, void *b, void *a, unsigned n) { 1407 int ret; 1408 OrigFn fn; 1409 VALGRIND_GET_ORIG_FN(fn); 1410 DO_CREQ_v_WW(TSREQ_CYCLIC_BARRIER_INIT, void*,b, unsigned long, n); 1411 CALL_FN_W_WWW(ret, fn, b, a, n); 1412 return ret; 1413 } 1414 /*----------------------------------------------------------------*/ 1415 /*--- pthread_rwlock_t functions ---*/ 1416 /*----------------------------------------------------------------*/ 1417 1418 /* Handled: pthread_rwlock_init pthread_rwlock_destroy 1419 pthread_rwlock_rdlock 1420 pthread_rwlock_wrlock 1421 pthread_rwlock_unlock 1422 1423 Unhandled: pthread_rwlock_timedrdlock 1424 pthread_rwlock_tryrdlock 1425 1426 pthread_rwlock_timedwrlock 1427 pthread_rwlock_trywrlock 1428 */ 1429 1430 // pthread_rwlock_init 1431 static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl, 1432 pthread_rwlockattr_t* attr) 1433 { 1434 int ret; 1435 OrigFn fn; 1436 VALGRIND_GET_ORIG_FN(fn); 1437 if (TRACE_PTH_FNS) { 1438 fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr); 1439 } 1440 1441 CALL_FN_W_WW(ret, fn, rwl,attr); 1442 1443 if (ret == 0 /*success*/) { 1444 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_CREATE_POST, 1445 pthread_rwlock_t*,rwl); 1446 } else { 1447 DO_PthAPIerror( "pthread_rwlock_init", ret ); 1448 } 1449 1450 if (TRACE_PTH_FNS) { 1451 fprintf(stderr, " :: rwl_init -> %d >>\n", ret); 1452 } 1453 return ret; 1454 } 1455 1456 PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init 1457 pthread_rwlock_t *rwl, 1458 pthread_rwlockattr_t* attr) 1459 { 1460 return pthread_rwlock_init_WRK(rwl, attr); 1461 } 1462 1463 PTH_FUNC(int, pthreadZurwlockZuinit$Za, // pthread_rwlock_init$* 1464 pthread_rwlock_t *rwl, 1465 pthread_rwlockattr_t* attr) 1466 { 1467 return pthread_rwlock_init_WRK(rwl, attr); 1468 } 1469 1470 // pthread_rwlock_destroy 1471 static int pthread_rwlock_destroy_WRK( pthread_rwlock_t *rwl) 1472 { 1473 int ret; 1474 OrigFn fn; 1475 VALGRIND_GET_ORIG_FN(fn); 1476 if (TRACE_PTH_FNS) { 1477 fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr); 1478 } 1479 1480 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, 1481 pthread_rwlock_t*,rwl); 1482 1483 CALL_FN_W_W(ret, fn, rwl); 1484 1485 if (ret != 0) { 1486 DO_PthAPIerror( "pthread_rwlock_destroy", ret ); 1487 } 1488 1489 if (TRACE_PTH_FNS) { 1490 fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret); 1491 } 1492 return ret; 1493 } 1494 1495 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy 1496 pthread_rwlock_t *rwl) 1497 { 1498 return pthread_rwlock_destroy_WRK(rwl); 1499 } 1500 1501 PTH_FUNC(int, pthreadZurwlockZudestroy$Za, // pthread_rwlock_destroy$* 1502 pthread_rwlock_t *rwl) 1503 { 1504 return pthread_rwlock_destroy_WRK(rwl); 1505 } 1506 1507 1508 // pthread_rwlock_wrlock 1509 static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock) 1510 { 1511 int ret; 1512 OrigFn fn; 1513 VALGRIND_GET_ORIG_FN(fn); 1514 if (TRACE_PTH_FNS) { 1515 fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr); 1516 } 1517 1518 1519 IGNORE_ALL_SYNC_BEGIN(); 1520 CALL_FN_W_W(ret, fn, rwlock); 1521 IGNORE_ALL_SYNC_END(); 1522 1523 if (ret == 0 /*success*/) { 1524 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 1525 pthread_rwlock_t*,rwlock, long,1/*isW*/); 1526 } else { 1527 DO_PthAPIerror( "pthread_rwlock_wrlock", ret ); 1528 } 1529 1530 if (TRACE_PTH_FNS) { 1531 fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret); 1532 } 1533 return ret; 1534 } 1535 1536 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock 1537 pthread_rwlock_t* rwlock) 1538 { 1539 return pthread_rwlock_wrlock_WRK(rwlock); 1540 } 1541 1542 PTH_FUNC(int, pthreadZurwlockZuwrlock$Za, // pthread_rwlock_wrlock$* 1543 pthread_rwlock_t* rwlock) 1544 { 1545 return pthread_rwlock_wrlock_WRK(rwlock); 1546 } 1547 1548 // pthread_rwlock_rdlock 1549 static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock) 1550 { 1551 int ret; 1552 OrigFn fn; 1553 VALGRIND_GET_ORIG_FN(fn); 1554 if (TRACE_PTH_FNS) { 1555 fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr); 1556 } 1557 1558 IGNORE_ALL_SYNC_BEGIN(); 1559 CALL_FN_W_W(ret, fn, rwlock); 1560 IGNORE_ALL_SYNC_END(); 1561 1562 if (ret == 0 /*success*/) { 1563 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 1564 pthread_rwlock_t*,rwlock, long,0/*!isW*/); 1565 } else { 1566 DO_PthAPIerror( "pthread_rwlock_rdlock", ret ); 1567 } 1568 1569 if (TRACE_PTH_FNS) { 1570 fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret); 1571 } 1572 return ret; 1573 } 1574 1575 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock 1576 pthread_rwlock_t* rwlock) 1577 { 1578 return pthread_rwlock_rdlock_WRK(rwlock); 1579 } 1580 1581 PTH_FUNC(int, pthreadZurwlockZurdlock$Za, // pthread_rwlock_rdlock$* 1582 pthread_rwlock_t* rwlock) 1583 { 1584 return pthread_rwlock_rdlock_WRK(rwlock); 1585 } 1586 1587 // pthread_rwlock_trywrlock 1588 static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock) 1589 { 1590 int ret; 1591 OrigFn fn; 1592 VALGRIND_GET_ORIG_FN(fn); 1593 if (TRACE_PTH_FNS) { 1594 fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr); 1595 } 1596 1597 IGNORE_ALL_SYNC_BEGIN(); 1598 CALL_FN_W_W(ret, fn, rwlock); 1599 IGNORE_ALL_SYNC_END(); 1600 1601 /* There's a hole here: libpthread now knows the lock is locked, 1602 but the tool doesn't, so some other thread could run and detect 1603 that the lock has been acquired by someone (this thread). Does 1604 this matter? Not sure, but I don't think so. */ 1605 1606 if (ret == 0 /*success*/) { 1607 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 1608 pthread_rwlock_t*,rwlock, long,1/*isW*/); 1609 } else { 1610 if (ret != EBUSY) 1611 DO_PthAPIerror( "pthread_rwlock_trywrlock", ret ); 1612 } 1613 1614 if (TRACE_PTH_FNS) { 1615 fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret); 1616 } 1617 return ret; 1618 } 1619 1620 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock 1621 pthread_rwlock_t* rwlock) 1622 { 1623 return pthread_rwlock_trywrlock_WRK(rwlock); 1624 } 1625 1626 PTH_FUNC(int, pthreadZurwlockZutrywrlock$Za, // pthread_rwlock_trywrlock$* 1627 pthread_rwlock_t* rwlock) 1628 { 1629 return pthread_rwlock_trywrlock_WRK(rwlock); 1630 } 1631 1632 // pthread_rwlock_tryrdlock 1633 static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock) 1634 { 1635 int ret; 1636 OrigFn fn; 1637 VALGRIND_GET_ORIG_FN(fn); 1638 if (TRACE_PTH_FNS) { 1639 fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr); 1640 } 1641 1642 IGNORE_ALL_SYNC_BEGIN(); 1643 CALL_FN_W_W(ret, fn, rwlock); 1644 IGNORE_ALL_SYNC_END(); 1645 1646 /* There's a hole here: libpthread now knows the lock is locked, 1647 but the tool doesn't, so some other thread could run and detect 1648 that the lock has been acquired by someone (this thread). Does 1649 this matter? Not sure, but I don't think so. */ 1650 1651 if (ret == 0 /*success*/) { 1652 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 1653 pthread_rwlock_t*,rwlock, long,0/*!isW*/); 1654 } else { 1655 if (ret != EBUSY) 1656 DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret ); 1657 } 1658 1659 if (TRACE_PTH_FNS) { 1660 fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret); 1661 } 1662 return ret; 1663 } 1664 1665 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock 1666 pthread_rwlock_t* rwlock) 1667 { 1668 return pthread_rwlock_tryrdlock_WRK(rwlock); 1669 } 1670 1671 PTH_FUNC(int, pthreadZurwlockZutryrdlock$Za, // pthread_rwlock_tryrdlock$* 1672 pthread_rwlock_t* rwlock) 1673 { 1674 return pthread_rwlock_tryrdlock_WRK(rwlock); 1675 } 1676 1677 1678 // pthread_rwlock_unlock 1679 static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock) 1680 { 1681 int ret; 1682 OrigFn fn; 1683 VALGRIND_GET_ORIG_FN(fn); 1684 if (TRACE_PTH_FNS) { 1685 fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr); 1686 } 1687 1688 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, 1689 pthread_rwlock_t*,rwlock); 1690 1691 IGNORE_ALL_SYNC_BEGIN(); 1692 CALL_FN_W_W(ret, fn, rwlock); 1693 IGNORE_ALL_SYNC_END(); 1694 1695 if (ret != 0 /*error*/) { 1696 DO_PthAPIerror( "pthread_rwlock_unlock", ret ); 1697 } 1698 1699 if (TRACE_PTH_FNS) { 1700 fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret); 1701 } 1702 return ret; 1703 } 1704 1705 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock 1706 pthread_rwlock_t* rwlock) 1707 { 1708 return pthread_rwlock_unlock_WRK(rwlock); 1709 } 1710 1711 PTH_FUNC(int, pthreadZurwlockZuunlock$Za, // pthread_rwlock_unlock$* 1712 pthread_rwlock_t* rwlock) 1713 { 1714 return pthread_rwlock_unlock_WRK(rwlock); 1715 } 1716 1717 /*----------------------------------------------------------------*/ 1718 /*--- POSIX semaphores ---*/ 1719 /*----------------------------------------------------------------*/ 1720 1721 #include <semaphore.h> 1722 1723 #define TRACE_SEM_FNS 0 1724 1725 /* Handled: 1726 int sem_init(sem_t *sem, int pshared, unsigned value); 1727 int sem_destroy(sem_t *sem); 1728 int sem_wait(sem_t *sem); 1729 int sem_post(sem_t *sem); 1730 int sem_trywait(sem_t *sem); 1731 1732 Unhandled: 1733 int sem_timedwait(sem_t *restrict sem, 1734 const struct timespec *restrict abs_timeout); 1735 */ 1736 1737 /* glibc-2.5 has sem_init@@GLIBC_2.2.5 (amd64-linux) 1738 and sem_init@@GLIBC_2.1 (x86-linux): match sem_init@* 1739 sem_init is not implemented for Darwin. */ 1740 PTH_FUNC(int, semZuinitZAZa, sem_t* sem, int pshared, unsigned long value) 1741 { 1742 OrigFn fn; 1743 int ret; 1744 VALGRIND_GET_ORIG_FN(fn); 1745 1746 if (TRACE_SEM_FNS) { 1747 fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value); 1748 fflush(stderr); 1749 } 1750 1751 CALL_FN_W_WWW(ret, fn, sem,pshared,value); 1752 1753 if (ret == 0) { 1754 DO_CREQ_v_WW(TSREQ_POSIX_SEM_INIT_POST, 1755 sem_t*, sem, unsigned long, value); 1756 } else { 1757 DO_PthAPIerror( "sem_init", errno ); 1758 } 1759 1760 if (TRACE_SEM_FNS) { 1761 fprintf(stderr, " sem_init -> %d >>\n", ret); 1762 fflush(stderr); 1763 } 1764 1765 return ret; 1766 } 1767 1768 1769 static int sem_destroy_WRK(sem_t* sem) 1770 { 1771 OrigFn fn; 1772 int ret; 1773 VALGRIND_GET_ORIG_FN(fn); 1774 1775 if (TRACE_SEM_FNS) { 1776 fprintf(stderr, "<< sem_destroy(%p) ", sem); 1777 fflush(stderr); 1778 } 1779 1780 DO_CREQ_v_W(TSREQ_POSIX_SEM_DESTROY_PRE, sem_t*, sem); 1781 1782 CALL_FN_W_W(ret, fn, sem); 1783 1784 if (ret != 0) { 1785 DO_PthAPIerror( "sem_destroy", errno ); 1786 } 1787 1788 if (TRACE_SEM_FNS) { 1789 fprintf(stderr, " sem_destroy -> %d >>\n", ret); 1790 fflush(stderr); 1791 } 1792 1793 return ret; 1794 } 1795 1796 /* glibc-2.5 has sem_destroy@@GLIBC_2.2.5 (amd64-linux) 1797 and sem_destroy@@GLIBC_2.1 (x86-linux); match sem_destroy@* */ 1798 PTH_FUNC(int, semZudestroyZAZa, sem_t* sem) 1799 { 1800 return sem_destroy_WRK(sem); 1801 } 1802 1803 // Darwin has sem_destroy. 1804 PTH_FUNC(int, semZudestroy, sem_t* sem) 1805 { 1806 return sem_destroy_WRK(sem); 1807 } 1808 1809 /* glibc-2.5 has sem_wait (amd64-linux); match sem_wait 1810 and sem_wait@@GLIBC_2.1 (x86-linux); match sem_wait@* */ 1811 /* wait: decrement semaphore - acquire lockage */ 1812 static int sem_wait_WRK(sem_t* sem, const char *name, int is_try) 1813 { 1814 OrigFn fn; 1815 int ret; 1816 VALGRIND_GET_ORIG_FN(fn); 1817 1818 if (TRACE_SEM_FNS) { 1819 fprintf(stderr, "<< %s(%p) ", name, sem); 1820 fflush(stderr); 1821 } 1822 1823 CALL_FN_W_W(ret, fn, sem); 1824 1825 if (ret == 0) { 1826 DO_CREQ_v_W(TSREQ_WAIT, sem_t*,sem); 1827 } else { 1828 if (!is_try) { 1829 DO_PthAPIerror( name, errno ); 1830 } 1831 } 1832 1833 if (TRACE_SEM_FNS) { 1834 fprintf(stderr, " %s -> %d >>\n", name, ret); 1835 fflush(stderr); 1836 } 1837 1838 return ret; 1839 } 1840 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ 1841 return sem_wait_WRK(sem, "sem_wait", 0); 1842 } 1843 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */ 1844 return sem_wait_WRK(sem, "sem_wait", 0); 1845 } 1846 PTH_FUNC(int, semZuwait$Za, sem_t* sem) { /* sem_wait$* */ 1847 return sem_wait_WRK(sem, "sem_wait", 0); 1848 } 1849 PTH_FUNC(int, semZutrywait, sem_t* sem) { /* sem_trywait */ 1850 return sem_wait_WRK(sem, "sem_trywait", 1); 1851 } 1852 PTH_FUNC(int, semZutrywaitZAZa, sem_t* sem) { /* sem_trywait@* */ 1853 return sem_wait_WRK(sem, "sem_trywait", 1); 1854 } 1855 PTH_FUNC(int, semZutrywait$Za, sem_t* sem) { /* sem_trywait$* */ 1856 return sem_wait_WRK(sem, "sem_trywait", 1); 1857 } 1858 1859 1860 1861 1862 /* glibc-2.5 has sem_post (amd64-linux); match sem_post 1863 and sem_post@@GLIBC_2.1 (x86-linux); match sem_post@* */ 1864 /* post: increment semaphore - release lockage */ 1865 static int sem_post_WRK(OrigFn fn, sem_t* sem) 1866 { 1867 int ret; 1868 1869 1870 if (TRACE_SEM_FNS) { 1871 fprintf(stderr, "<< sem_post(%p) ", sem); 1872 fflush(stderr); 1873 } 1874 1875 DO_CREQ_v_W(TSREQ_SIGNAL, sem_t*,sem); 1876 1877 CALL_FN_W_W(ret, fn, sem); 1878 1879 if (ret != 0) { 1880 DO_PthAPIerror( "sem_post", errno ); 1881 } 1882 1883 if (TRACE_SEM_FNS) { 1884 fprintf(stderr, " sem_post -> %d >>\n", ret); 1885 fflush(stderr); 1886 } 1887 1888 return ret; 1889 } 1890 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ 1891 OrigFn fn; 1892 VALGRIND_GET_ORIG_FN(fn); 1893 return sem_post_WRK(fn, sem); 1894 } 1895 PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */ 1896 OrigFn fn; 1897 VALGRIND_GET_ORIG_FN(fn); 1898 return sem_post_WRK(fn, sem); 1899 } 1900 PTH_FUNC(int, semZupost$Za, sem_t* sem) { /* sem_post$* */ 1901 OrigFn fn; 1902 VALGRIND_GET_ORIG_FN(fn); 1903 return sem_post_WRK(fn, sem); 1904 } 1905 1906 /* From man page: 1907 sem_t *sem_open(const char *name, int oflag, ...); 1908 ... 1909 The oflag argument controls whether the semaphore is created or merely 1910 accessed by the call to sem_open(). The following flag bits may be 1911 set in oflag: 1912 ... 1913 If O_CREAT is set and the semaphore already exists, then O_CREAT has no 1914 effect, except as noted under O_EXCL. Otherwise, sem_open() creates a 1915 named semaphore. The O_CREAT flag requires a third and a fourth 1916 argument: mode, which is of type mode_t, and value, which is of 1917 type unsigned int. The semaphore is created with an initial value of value. 1918 */ 1919 static sem_t *sem_open_WRK(OrigFn fn, 1920 const char *name, int oflag, 1921 mode_t mode, unsigned int value) { 1922 1923 sem_t *ret; 1924 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value); 1925 if ((oflag & O_CREAT) && 1926 value > 0 && 1927 ret != SEM_FAILED) { 1928 // This semaphore has been created with a non-zero value. 1929 // The semaphore is initialized only on the first call to sem_open, 1930 // next call will return an existing semaphore. 1931 // Ideally, we need to handle it like sem_init with a non-zero value. 1932 // But in such case we also need to handle sem_unlink. 1933 // 1934 // To avoid this complexity we simply do a SIGNAL here. 1935 DO_CREQ_v_W(TSREQ_SIGNAL, sem_t*, ret); 1936 } 1937 return ret; 1938 } 1939 1940 PTH_FUNC(sem_t *, semZuopen, const char *name, int oflag, 1941 mode_t mode, unsigned int value) { /* sem_open */ 1942 OrigFn fn; 1943 VALGRIND_GET_ORIG_FN(fn); 1944 return sem_open_WRK(fn, name, oflag, mode, value); 1945 } 1946 1947 PTH_FUNC(sem_t *, semZuopenZAZa, const char *name, int oflag, 1948 mode_t mode, unsigned int value) { /* sem_open@* */ 1949 OrigFn fn; 1950 VALGRIND_GET_ORIG_FN(fn); 1951 return sem_open_WRK(fn, name, oflag, mode, value); 1952 } 1953 1954 1955 // atexit -> exit create a h-b arc. 1956 static void *AtExitMagic(void) { 1957 return (void*)0x12345678; 1958 } 1959 1960 #define ATEXIT_BODY { \ 1961 OrigFn fn;\ 1962 long ret;\ 1963 VALGRIND_GET_ORIG_FN(fn);\ 1964 CALL_FN_W_W(ret, fn, callback);\ 1965 DO_CREQ_v_W(TSREQ_SIGNAL, void*, AtExitMagic());\ 1966 return ret;\ 1967 }\ 1968 1969 NONE_FUNC(long, atexit, void *callback) ATEXIT_BODY 1970 LIBC_FUNC(long, atexit, void *callback) ATEXIT_BODY 1971 1972 #define EXIT_BODY { \ 1973 OrigFn fn;\ 1974 VALGRIND_GET_ORIG_FN(fn);\ 1975 do_wait(AtExitMagic());\ 1976 CALL_FN_v_W(fn, x);\ 1977 }\ 1978 1979 LIBC_FUNC(void, exit, int x) EXIT_BODY 1980 NONE_FUNC(void, exit, int x) EXIT_BODY 1981 1982 // socket/file IO that creates happens-before arcs. 1983 static void *SocketMagic(long s) { 1984 return (void*)0xDEADFBAD; 1985 } 1986 1987 LIBC_FUNC(int, epoll_wait, int epfd, void * events, int maxevents, int timeout) { 1988 OrigFn fn; 1989 long ret; 1990 void *o; 1991 VALGRIND_GET_ORIG_FN(fn); 1992 // fprintf(stderr, "T%d socket epoll_wait: %d\n", VALGRIND_TS_THREAD_ID(), epfd); 1993 CALL_FN_W_WWWW(ret, fn, epfd, events, maxevents, timeout); 1994 o = SocketMagic(epfd); 1995 do_wait(o); 1996 return ret; 1997 } 1998 1999 LIBC_FUNC(int, epoll_ctl, int epfd, int op, int fd, void *event) { 2000 OrigFn fn; 2001 long ret; 2002 void *o; 2003 VALGRIND_GET_ORIG_FN(fn); 2004 // fprintf(stderr, "T%d socket epoll_ctl: %d\n", VALGRIND_TS_THREAD_ID(), epfd); 2005 o = SocketMagic(epfd); 2006 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2007 CALL_FN_W_WWWW(ret, fn, epfd, op, fd, event); 2008 return ret; 2009 } 2010 2011 PTH_FUNC(long, send, int s, void *buf, long len, int flags) { 2012 OrigFn fn; 2013 long ret; 2014 void *o; 2015 VALGRIND_GET_ORIG_FN(fn); 2016 // fprintf(stderr, "T%d socket send: %d %ld\n", VALGRIND_TS_THREAD_ID(), s, len); 2017 o = SocketMagic(s); 2018 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2019 CALL_FN_W_WWWW(ret, fn, s, buf, len, flags); 2020 return ret; 2021 } 2022 2023 PTH_FUNC(long, sendmsg, int s, void *msg, int flags) { 2024 OrigFn fn; 2025 long ret; 2026 void *o; 2027 VALGRIND_GET_ORIG_FN(fn); 2028 o = SocketMagic(s); 2029 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2030 CALL_FN_W_WWW(ret, fn, s, msg, flags); 2031 return ret; 2032 } 2033 2034 // TODO(timurrrr): sendto 2035 2036 PTH_FUNC(long, recv, int s, void *buf, long len, int flags) { 2037 OrigFn fn; 2038 long ret; 2039 void *o; 2040 VALGRIND_GET_ORIG_FN(fn); 2041 CALL_FN_W_WWWW(ret, fn, s, buf, len, flags); 2042 // fprintf(stderr, "T%d socket recv: %d %ld %ld\n", VALGRIND_TS_THREAD_ID(), s, len, ret); 2043 o = SocketMagic(s); 2044 if (ret >= 0) { 2045 // Do client request only if we received something 2046 // or the connection was closed. 2047 do_wait(o); 2048 } 2049 return ret; 2050 } 2051 2052 PTH_FUNC(long, recvmsg, int s, void *msg, int flags) { 2053 OrigFn fn; 2054 long ret; 2055 void *o; 2056 VALGRIND_GET_ORIG_FN(fn); 2057 CALL_FN_W_WWW(ret, fn, s, msg, flags); 2058 o = SocketMagic(s); 2059 if (ret >= 0) { 2060 // Do client request only if we received something 2061 // or the connection was closed. 2062 do_wait(o); 2063 } 2064 return ret; 2065 } 2066 2067 // TODO(timurrrr): recvfrom 2068 2069 PTH_FUNC(long, read, int s, void *a2, long count) { 2070 OrigFn fn; 2071 long ret; 2072 void *o; 2073 VALGRIND_GET_ORIG_FN(fn); 2074 CALL_FN_W_WWW(ret, fn, s, a2, count); 2075 // fprintf(stderr, "T%d socket read: %d %ld %ld\n", VALGRIND_TS_THREAD_ID(), s, count, ret); 2076 o = SocketMagic(s); 2077 if (ret >= 0) { 2078 // Do client request only if we read something or the EOF was reached. 2079 do_wait(o); 2080 } 2081 return ret; 2082 } 2083 2084 PTH_FUNC(long, write, int s, void *a2, long a3) { 2085 OrigFn fn; 2086 long ret; 2087 void *o; 2088 VALGRIND_GET_ORIG_FN(fn); 2089 // fprintf(stderr, "T%d socket write: %d\n", VALGRIND_TS_THREAD_ID(), s); 2090 o = SocketMagic(s); 2091 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2092 CALL_FN_W_WWW(ret, fn, s, a2, a3); 2093 return ret; 2094 } 2095 2096 /* Linux: unlink 2097 * Darwin: unlink */ 2098 LIBC_FUNC(long, unlink, void *path) { 2099 OrigFn fn; 2100 long ret; 2101 void *o; 2102 VALGRIND_GET_ORIG_FN(fn); 2103 o = SocketMagic((long)path); 2104 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2105 CALL_FN_W_W(ret, fn, path); 2106 return ret; 2107 } 2108 2109 /* Linux: open 2110 * Darwin: open$NOCANCEL$UNIX2003 */ 2111 static int open_WRK(void *path, int flags, int mode) { 2112 OrigFn fn; 2113 long ret; 2114 void *o; 2115 VALGRIND_GET_ORIG_FN(fn); 2116 o = SocketMagic((long)path); 2117 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2118 CALL_FN_W_WWW(ret, fn, path, flags, mode); 2119 do_wait(o); 2120 return ret; 2121 } 2122 2123 LIBC_FUNC(int, open, void *path, int flags, int mode) { 2124 return open_WRK(path, flags, mode); 2125 } 2126 LIBC_FUNC(int, open$Za, void *path, int flags, int mode) { 2127 return open_WRK(path, flags, mode); 2128 } 2129 2130 /* Linux: rmdir 2131 * Darwin: rmdir */ 2132 LIBC_FUNC(int, rmdir, void *path) { 2133 OrigFn fn; 2134 long ret; 2135 void *o; 2136 VALGRIND_GET_ORIG_FN(fn); 2137 o = SocketMagic((long)path); 2138 DO_CREQ_v_W(TSREQ_SIGNAL, void*, o); 2139 CALL_FN_W_W(ret, fn, path); 2140 return ret; 2141 } 2142 2143 /* Linux: opendir 2144 * Darwin: opendir$UNIX2003 */ 2145 static long opendir_WRK(void *path) { 2146 OrigFn fn; 2147 long ret; 2148 void *o; 2149 VALGRIND_GET_ORIG_FN(fn); 2150 CALL_FN_W_W(ret, fn, path); 2151 o = SocketMagic((long)path); 2152 do_wait(o); 2153 return ret; 2154 } 2155 2156 LIBC_FUNC(long, opendir, void *path) { 2157 return opendir_WRK(path); 2158 } 2159 2160 LIBC_FUNC(long, opendir$Za, void *path) { 2161 return opendir_WRK(path); 2162 } 2163 2164 #ifndef ANDROID 2165 LIBC_FUNC(long, lockf, long fd, long cmd, OFF_T offset) { 2166 // TODO: this doesn't support locking file subsections 2167 const long offset_magic = 0xFEB0ACC0; 2168 OrigFn fn; 2169 long ret; 2170 VALGRIND_GET_ORIG_FN(fn); 2171 if (cmd == F_ULOCK) 2172 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, 2173 long, fd ^ offset_magic); 2174 CALL_FN_W_2WO_T(ret, fn, fd, cmd, offset); 2175 if (cmd == F_LOCK && ret == 0) 2176 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, 2177 long, fd ^ offset_magic, 2178 long, 1/*is_w*/); 2179 2180 return ret; 2181 } 2182 #endif 2183 2184 /* 2185 Support for pthread_once and function-level static objects. 2186 2187 pthread_once is supported by simply ignoring everything that happens 2188 inside pthread_once. 2189 2190 Another approach would be to SIGNAL when pthread_once with a given 2191 pthread_once_t is called for the first time and to WAIT after 2192 each pthread_once. But implementing this is a bit tricky and probably 2193 not worth it. 2194 2195 Thread safe initialization of function-level static objects is 2196 supported in gcc (strarting from 4.something). 2197 From gcc/cp/decl.c: 2198 -------------------------------------------------------------- 2199 Emit code to perform this initialization but once. This code 2200 looks like: 2201 2202 static <type> guard; 2203 if (!guard.first_byte) { 2204 if (__cxa_guard_acquire (&guard)) { 2205 bool flag = false; 2206 try { 2207 // Do initialization. 2208 flag = true; __cxa_guard_release (&guard); 2209 // Register variable for destruction at end of program. 2210 } catch { 2211 if (!flag) __cxa_guard_abort (&guard); 2212 } 2213 } 2214 -------------------------------------------------------------- 2215 So, when __cxa_guard_acquire returns true, we start ignoring all accesses 2216 and in __cxa_guard_release we stop ignoring them. 2217 We also need to ignore all accesses inside these two functions. 2218 2219 For examples, see test106 and test108 at 2220 http://code.google.com/p/data-race-test/source/browse/trunk/unittest/racecheck_unittest.cc 2221 */ 2222 2223 PTH_FUNC(int, pthreadZuonce, void *ctl, void *rtn) { 2224 OrigFn fn; 2225 int ret; 2226 VALGRIND_GET_ORIG_FN(fn); 2227 IGNORE_ALL_ACCESSES_BEGIN(); 2228 // fprintf(stderr, "T%d: ->pthread_once\n", VALGRIND_TS_THREAD_ID); 2229 CALL_FN_W_WW(ret, fn, ctl, rtn); 2230 // fprintf(stderr, "T%d: <-pthread_once\n", VALGRIND_TS_THREAD_ID); 2231 IGNORE_ALL_ACCESSES_END(); 2232 return ret; 2233 } 2234 2235 LIBSTDCXX_FUNC(long, ZuZucxaZuguardZuacquire, void *p) { 2236 OrigFn fn; 2237 long ret; 2238 VALGRIND_GET_ORIG_FN(fn); 2239 // fprintf(stderr, "T%d: ->__cxa_guard_acquire\n", VALGRIND_TS_THREAD_ID()); 2240 IGNORE_ALL_ACCESSES_BEGIN(); 2241 CALL_FN_W_W(ret, fn, p); 2242 // fprintf(stderr, "T%d: <-__cxa_guard_acquire\n", VALGRIND_TS_THREAD_ID()); 2243 if (!ret) { 2244 IGNORE_ALL_ACCESSES_END(); 2245 } 2246 return ret; 2247 } 2248 LIBSTDCXX_FUNC(long, ZuZucxaZuguardZurelease, void *p) { 2249 OrigFn fn; 2250 long ret; 2251 VALGRIND_GET_ORIG_FN(fn); 2252 // fprintf(stderr, "T%d: ->__cxa_guard_release\n", VALGRIND_TS_THREAD_ID()); 2253 CALL_FN_W_W(ret, fn, p); 2254 // fprintf(stderr, "T%d: <-__cxa_guard_release\n", VALGRIND_TS_THREAD_ID()); 2255 IGNORE_ALL_ACCESSES_END(); 2256 return ret; 2257 } 2258 2259 2260 2261 2262 /*----------------------------------------------------------------*/ 2263 /*--- Replace glibc's wretched optimised string fns (again!) ---*/ 2264 /*----------------------------------------------------------------*/ 2265 /* Why we have to do all this nonsense: 2266 2267 Some implementations of strlen may read up to 7 bytes past the end 2268 of the string thus touching memory which may not belong to this 2269 string. 2270 2271 Such race is benign because the data read past the end of the 2272 string is not used. 2273 */ 2274 // --- MEMCPY ----------------------------------------------------- 2275 // 2276 #define MEMCPY(soname, fnname) \ 2277 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2278 ( void *dst, const void *src, SizeT len ); \ 2279 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2280 ( void *dst, const void *src, SizeT len ) \ 2281 { return Replace_memcpy(dst, src, len); } 2282 2283 MEMCPY(VG_Z_LIBC_SONAME, memcpy) 2284 MEMCPY(NONE, memcpy) 2285 /* icc9 blats these around all over the place. Not only in the main 2286 executable but various .so's. They are highly tuned and read 2287 memory beyond the source boundary (although work correctly and 2288 never go across page boundaries), so give errors when run natively, 2289 at least for misaligned source arg. Just intercepting in the exe 2290 only until we understand more about the problem. See 2291 http://bugs.kde.org/show_bug.cgi?id=139776 2292 */ 2293 MEMCPY(NONE, _intel_fast_memcpy) 2294 #if defined(VGO_linux) 2295 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy); 2296 #endif 2297 2298 // --- MEMMOVE ----------------------------------------------------- 2299 // 2300 #define MEMMOVE(soname, fnname) \ 2301 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2302 ( void *dst, const void *src, SizeT len ); \ 2303 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2304 ( void *dst, const void *src, SizeT len ) \ 2305 { return Replace_memmove(dst, src, len); } 2306 2307 MEMMOVE(VG_Z_LIBC_SONAME, memmove) 2308 MEMMOVE(NONE, memmove) 2309 #if defined(VGO_linux) 2310 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove); 2311 #endif 2312 2313 2314 // --- STRCHR and INDEX ------------------------------------------- 2315 // 2316 #define STRCHR(soname, fnname) \ 2317 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \ 2318 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \ 2319 { return Replace_strchr(s, c); } 2320 2321 // Apparently index() is the same thing as strchr() 2322 STRCHR(VG_Z_LIBC_SONAME, strchr) 2323 STRCHR(VG_Z_LIBC_SONAME, index) 2324 STRCHR(NONE, strchr) 2325 STRCHR(NONE, index) 2326 #if defined(VGO_linux) 2327 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) 2328 #endif 2329 2330 // --- STRRCHR RINDEX ----------------------------------------------------- 2331 // 2332 #define STRRCHR(soname, fnname) \ 2333 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str, int c ); \ 2334 char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str, int c ) \ 2335 { return Replace_strrchr(str, c); } 2336 2337 STRRCHR(VG_Z_LIBC_SONAME, strrchr) 2338 STRRCHR(VG_Z_LIBC_SONAME, rindex) 2339 STRRCHR(NONE, strrchr) 2340 STRRCHR(NONE, rindex) 2341 #if defined(VGO_linux) 2342 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) 2343 #endif 2344 2345 // --- STRCMP ----------------------------------------------------- 2346 // 2347 #define STRCMP(soname, fnname) \ 2348 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2349 ( const char* s1, const char* s2 ); \ 2350 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2351 ( const char* s1, const char* s2 ) \ 2352 { return Replace_strcmp(s1, s2); } 2353 2354 STRCMP(VG_Z_LIBC_SONAME, strcmp) 2355 STRCMP(NONE, strcmp) 2356 #if defined(VGO_linux) 2357 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) 2358 #endif 2359 2360 #define MEMCMP(soname, fnname) \ 2361 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2362 ( const char* s1, const char* s2 , size_t n); \ 2363 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2364 ( const char* s1, const char* s2 , size_t n) \ 2365 { return Replace_memcmp(s1, s2, n); } 2366 2367 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_ssse3) 2368 MEMCMP(VG_Z_LIBC_SONAME, memcmp) 2369 MEMCMP(NONE, memcmp) 2370 #if defined(VGO_linux) 2371 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp) 2372 #endif 2373 2374 #define MEMCHR(soname, fnname) \ 2375 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \ 2376 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \ 2377 { return Replace_memchr(s, c, n); } 2378 2379 MEMCHR(VG_Z_LIBC_SONAME, memchr) 2380 MEMCHR(NONE, memchr) 2381 2382 #define STRNCMP(soname, fnname) \ 2383 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2384 ( const char* s1, const char* s2, size_t n); \ 2385 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ 2386 ( const char* s1, const char* s2, size_t n) \ 2387 { return Replace_strncmp(s1, s2, n); } 2388 2389 STRNCMP(VG_Z_LIBC_SONAME, strncmp) 2390 STRNCMP(NONE, strncmp) 2391 #if defined(VGO_linux) 2392 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) 2393 #endif 2394 2395 // --- STRLEN ----------------------------------------------------- 2396 // 2397 // Note that this replacement often doesn't get used because gcc inlines 2398 // calls to strlen() with its own built-in version. This can be very 2399 // confusing if you aren't expecting it. Other small functions in this file 2400 // may also be inline by gcc. 2401 #define STRLEN(soname, fnname) \ 2402 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \ 2403 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \ 2404 { return Replace_strlen(str); } 2405 2406 STRLEN(VG_Z_LIBC_SONAME, strlen) 2407 STRLEN(NONE, strlen) 2408 #if defined(VGO_linux) 2409 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) 2410 #endif 2411 2412 // --- STRCPY ----------------------------------------------------- 2413 // 2414 #define STRCPY(soname, fnname) \ 2415 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \ 2416 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \ 2417 { return Replace_strcpy(dst, src); } 2418 2419 STRCPY(VG_Z_LIBC_SONAME, strcpy) 2420 STRCPY(NONE, strcpy) 2421 #if defined(VGO_linux) 2422 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) 2423 #endif 2424 2425 // --- STRNCPY ----------------------------------------------------- 2426 // 2427 #define STRNCPY(soname, fnname) \ 2428 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src, size_t n ); \ 2429 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src, size_t n ) \ 2430 { return Replace_strncpy(dst, src, n); } 2431 2432 STRNCPY(VG_Z_LIBC_SONAME, strncpy) 2433 STRNCPY(NONE, strncpy) 2434 #if defined(VGO_linux) 2435 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy) 2436 #endif 2437 2438 // --- STRCAT ----------------------------------------------------- 2439 // 2440 #define STRCAT(soname, fnname) \ 2441 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src); \ 2442 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src) \ 2443 { return Replace_strcat(dst, src); } 2444 2445 STRCAT(VG_Z_LIBC_SONAME, strcat) 2446 STRCAT(NONE, strcat) 2447 #if defined(VGO_linux) 2448 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat) 2449 #endif 2450 2451 // --- STPCPY ----------------------------------------------------- 2452 // 2453 #define STPCPY(soname, fnname) \ 2454 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \ 2455 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \ 2456 { return Replace_stpcpy(dst, src); } 2457 2458 STPCPY(VG_Z_LIBC_SONAME, stpcpy) 2459 STPCPY(NONE, stpcpy) 2460 #if defined(VGO_linux) 2461 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy) 2462 #endif 2463 2464 //------------------------ Annotations ---------------- {{{1 2465 2466 2467 2468 #define ANN_FUNC(ret_ty, f, args...) \ 2469 ret_ty I_WRAP_SONAME_FNNAME_ZZ(Za,f)(args); \ 2470 ret_ty I_WRAP_SONAME_FNNAME_ZZ(Za,f)(args) 2471 2472 2473 #define ANN_TRACE(args...) \ 2474 do{\ 2475 if(TRACE_ANN_FNS){\ 2476 int tid = VALGRIND_TS_THREAD_ID();\ 2477 int sid = VALGRIND_TS_SEGMENT_ID();\ 2478 fprintf(stderr, args);\ 2479 if(tid != 999999 && sid != 999999) fflush(stderr);\ 2480 }\ 2481 }while(0) 2482 2483 ANN_FUNC(int, RunningOnValgrind, void) { 2484 return 1; 2485 } 2486 2487 ANN_FUNC(const char *, ThreadSanitizerQuery, const char *query) { 2488 Word res; 2489 DO_CREQ_W_WW(res, TSREQ_THREAD_SANITIZER_QUERY, const char*, query, long, 0); 2490 return (const char *)res; 2491 } 2492 2493 ANN_FUNC(void, AnnotateFlushState, const char *unused_file, int unused_line) { 2494 DO_CREQ_v_v(TSREQ_FLUSH_STATE); 2495 } 2496 2497 ANN_FUNC(void, AnnotateRWLockCreate, const char *file, int line, void *lock) 2498 { 2499 const char *name = "AnnotateRWLockCreate"; 2500 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, lock, file, line); 2501 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_CREATE_POST, void*, lock, long, 0 /*non recur*/); 2502 } 2503 2504 ANN_FUNC(void, AnnotateRWLockDestroy, const char *file, int line, void *lock) 2505 { 2506 const char *name = "AnnotateRWLockDestroy"; 2507 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, lock, file, line); 2508 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, void*, lock); 2509 } 2510 2511 ANN_FUNC(void, AnnotateRWLockAcquired, const char *file, int line, void *lock, int is_w) 2512 { 2513 const char *name = "AnnotateRWLockAcquired"; 2514 ANN_TRACE("--#%d %s[%p] rw=%d %s:%d\n", tid, name, lock, is_w, file, line); 2515 DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void*,lock,long, (long)is_w); 2516 } 2517 2518 ANN_FUNC(void, AnnotateRWLockReleased, const char *file, int line, void *lock, int is_w) 2519 { 2520 const char *name = "AnnotateRWLockReleased"; 2521 ANN_TRACE("--#%d %s[%p] rw=%d %s:%d\n", tid, name, lock, is_w, file, line); 2522 DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void*, lock); 2523 } 2524 2525 ANN_FUNC(void, AnnotateCondVarWait, const char *file, int line, void *cv, void *lock) 2526 { 2527 const char *name = "AnnotateCondVarWait"; 2528 ANN_TRACE("--#%d %s[%p|%p] %s:%d\n", tid, name, cv, lock, file, line); 2529 do_wait(cv); 2530 } 2531 2532 ANN_FUNC(void, AnnotateCondVarSignal, const char *file, int line, void *cv) 2533 { 2534 const char *name = "AnnotateCondVarSignal"; 2535 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, cv, file, line); 2536 DO_CREQ_v_W(TSREQ_SIGNAL, void*,cv); 2537 } 2538 2539 ANN_FUNC(void, AnnotateCondVarSignalAll, const char *file, int line, void *cv) 2540 { 2541 const char *name = "AnnotateCondVarSignalAll"; 2542 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, cv, file, line); 2543 DO_CREQ_v_W(TSREQ_SIGNAL, void*,cv); 2544 } 2545 2546 ANN_FUNC(void, AnnotateHappensBefore, const char *file, int line, void *obj) 2547 { 2548 const char *name = "AnnotateHappensBefore"; 2549 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line); 2550 DO_CREQ_v_W(TSREQ_SIGNAL, void*, obj); 2551 } 2552 2553 ANN_FUNC(void, WTFAnnotateHappensBefore, const char *file, int line, void *obj) 2554 { 2555 const char *name = "WTFAnnotateHappensBefore"; 2556 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line); 2557 DO_CREQ_v_W(TSREQ_SIGNAL, void*, obj); 2558 } 2559 2560 ANN_FUNC(void, AnnotateHappensAfter, const char *file, int line, void *obj) 2561 { 2562 const char *name = "AnnotateHappensAfter"; 2563 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line); 2564 do_wait(obj); 2565 } 2566 2567 ANN_FUNC(void, WTFAnnotateHappensAfter, const char *file, int line, void *obj) 2568 { 2569 const char *name = "WTFAnnotateHappensAfter"; 2570 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line); 2571 do_wait(obj); 2572 } 2573 2574 ANN_FUNC(void, AnnotatePCQCreate, const char *file, int line, void *pcq) 2575 { 2576 const char *name = "AnnotatePCQCreate"; 2577 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line); 2578 DO_CREQ_v_W(TSREQ_PCQ_CREATE, void*,pcq); 2579 } 2580 2581 ANN_FUNC(void, AnnotatePCQDestroy, const char *file, int line, void *pcq) 2582 { 2583 const char *name = "AnnotatePCQDestroy"; 2584 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line); 2585 DO_CREQ_v_W(TSREQ_PCQ_DESTROY, void*,pcq); 2586 } 2587 2588 ANN_FUNC(void, AnnotatePCQPut, const char *file, int line, void *pcq) 2589 { 2590 const char *name = "AnnotatePCQPut"; 2591 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line); 2592 DO_CREQ_v_W(TSREQ_PCQ_PUT, void*,pcq); 2593 } 2594 2595 ANN_FUNC(void, AnnotatePCQGet, const char *file, int line, void *pcq) 2596 { 2597 const char *name = "AnnotatePCQGet"; 2598 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line); 2599 DO_CREQ_v_W(TSREQ_PCQ_GET, void*,pcq); 2600 } 2601 2602 ANN_FUNC(void, AnnotateExpectRace, const char *file, int line, void *mem, char *description) 2603 { 2604 const char *name = "AnnotateExpectRace"; 2605 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line); 2606 DO_CREQ_v_WWW(TSREQ_EXPECT_RACE, void*,mem, long, 1, char*,description); 2607 } 2608 2609 ANN_FUNC(void, AnnotateFlushExpectedRaces, const char *file, int line) 2610 { 2611 const char *name = __FUNCTION__; 2612 ANN_TRACE("--#%d %s\n", tid, name); 2613 DO_CREQ_v_v(TSREQ_FLUSH_EXPECTED_RACES); 2614 } 2615 2616 ANN_FUNC(void, AnnotateBenignRace, const char *file, int line, void *mem, char *description) 2617 { 2618 const char *name = "AnnotateBenignRace"; 2619 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line); 2620 DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, void*,mem, long, 1, char*,description); 2621 } 2622 2623 ANN_FUNC(void, AnnotateBenignRaceSized, const char *file, int line, void *mem, long size, char *description) 2624 { 2625 const char *name = "AnnotateBenignRace"; 2626 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line); 2627 DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, char*,(char*)mem, long, size, 2628 char*,description); 2629 } 2630 2631 ANN_FUNC(void, WTFAnnotateBenignRaceSized, const char *file, int line, void *mem, long size, char *description) 2632 { 2633 const char *name = "WTFAnnotateBenignRace"; 2634 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line); 2635 DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, char*,(char*)mem, long, size, 2636 char*,description); 2637 } 2638 2639 2640 ANN_FUNC(void, AnnotateNewMemory, char *file, int line, void *mem, long size) 2641 { 2642 const char *name = "AnnotateNewMemory"; 2643 ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line); 2644 DO_CREQ_v_WWWW(TSREQ_CLEAN_MEMORY, void*,mem, long, size, char*, file, long, (long)line); 2645 } 2646 2647 ANN_FUNC(void, AnnotatePublishMemoryRange, char *file, int line, void *mem, long size) 2648 { 2649 const char *name = "AnnotatePublishMemoryRange"; 2650 ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line); 2651 DO_CREQ_v_WW(TSREQ_PUBLISH_MEMORY_RANGE, void*, mem, long, size); 2652 } 2653 2654 ANN_FUNC(void, AnnotateUnpublishMemoryRange, char *file, int line, void *mem, long size) 2655 { 2656 const char *name = "AnnotateUnpublishMemoryRange"; 2657 ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line); 2658 DO_CREQ_v_WW(TSREQ_UNPUBLISH_MEMORY_RANGE, void*, mem, long, size); 2659 } 2660 2661 ANN_FUNC(void, AnnotateIgnoreReadsBegin, char *file, int line, void *mu) 2662 { 2663 const char *name = "AnnotateIgnoreReadsBegin"; 2664 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2665 DO_CREQ_v_W(TSREQ_IGNORE_READS_BEGIN, void*, mu); 2666 } 2667 2668 ANN_FUNC(void, AnnotateIgnoreReadsEnd, char *file, int line, void *mu) 2669 { 2670 const char *name = "AnnotateIgnoreReadsEnd"; 2671 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2672 DO_CREQ_v_W(TSREQ_IGNORE_READS_END, void*, mu); 2673 } 2674 2675 ANN_FUNC(void, AnnotateIgnoreWritesBegin, char *file, int line, void *mu) 2676 { 2677 const char *name = "AnnotateIgnoreWritesBegin"; 2678 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2679 DO_CREQ_v_W(TSREQ_IGNORE_WRITES_BEGIN, void*, mu); 2680 } 2681 2682 ANN_FUNC(void, AnnotateIgnoreWritesEnd, char *file, int line, void *mu) 2683 { 2684 const char *name = "AnnotateIgnoreWritesEnd"; 2685 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2686 DO_CREQ_v_W(TSREQ_IGNORE_WRITES_END, void*, mu); 2687 } 2688 2689 ANN_FUNC(void, AnnotateIgnoreSyncBegin, char* file, int line, void *mu) 2690 { 2691 const char *name = "AnnotateIgnoreSyncBegin"; 2692 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2693 DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_BEGIN, void*, mu); 2694 } 2695 2696 ANN_FUNC(void, AnnotateIgnoreSyncEnd, char* file, int line, void *mu) 2697 { 2698 const char *name = "AnnotateIgnoreSyncEnd"; 2699 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2700 DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_END, void*, mu); 2701 } 2702 2703 ANN_FUNC(void, AnnotateEnableRaceDetection, char *file, int line, int enable) 2704 { 2705 const char *name = "AnnotateEnableRaceDetection"; 2706 ANN_TRACE("--#%d %s[%d] %s:%d\n", tid, name, enable, file, line); 2707 DO_CREQ_v_W(enable == 0 ? TSREQ_GLOBAL_IGNORE_ON : TSREQ_GLOBAL_IGNORE_OFF, 2708 long, 0); 2709 } 2710 2711 ANN_FUNC(void, AnnotateThreadName, char *file, int line, const char *thread_name) 2712 { 2713 const char *name = "AnnotateThreadName"; 2714 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, thread_name, file, line); 2715 DO_CREQ_v_W(TSREQ_SET_THREAD_NAME, const char *, thread_name); 2716 } 2717 2718 ANN_FUNC(void, AnnotateMutexIsUsedAsCondVar, char *file, int line, void *mu) 2719 { 2720 const char *name = "AnnotateMutexIsUsedAsCondVar"; 2721 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2722 DO_CREQ_v_W(TSREQ_MUTEX_IS_USED_AS_CONDVAR, void*, mu); 2723 } 2724 2725 ANN_FUNC(void, AnnotateMutexIsNotPHB, char *file, int line, void *mu) 2726 { 2727 const char *name = "AnnotateMutexIsNotPhb"; 2728 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line); 2729 DO_CREQ_v_W(TSREQ_MUTEX_IS_NOT_PHB, void*, mu); 2730 } 2731 2732 ANN_FUNC(void, AnnotateTraceMemory, char *file, int line, void *mem) 2733 { 2734 const char *name = "AnnotateTraceMemory"; 2735 ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line); 2736 DO_CREQ_v_W(TSREQ_TRACE_MEM, void*, mem); 2737 } 2738 2739 #undef TRACE_ANN_FNS 2740 #define TRACE_ANN_FNS 1 2741 2742 ANN_FUNC(void, AnnotateNoOp, char *file, int line, void *mem) 2743 { 2744 const char *name = "AnnotateNoOp"; 2745 IGNORE_ALL_ACCESSES_BEGIN(); 2746 ANN_TRACE("--#%d/%d %s[%p] %s:%d\n", tid, sid, name, mem, file, line); 2747 IGNORE_ALL_ACCESSES_END(); 2748 } 2749 2750 ANN_FUNC(void, AnnotateSetVerbosity, char *file, int line, void *mem) 2751 { 2752 const char *name = "AnnotateSetVerbosity"; 2753 OrigFn fn; 2754 VALGRIND_GET_ORIG_FN(fn); 2755 fprintf(stderr, "%s fn=%p\n", name, (void*)fn.nraddr); 2756 ANN_TRACE("--#%d/%d %s[%p] %s:%d\n", tid, sid, name, mem, file, line); 2757 } 2758 2759 2760 2761 //-------------- NaCl Support -------------- {{{1 2762 // A bit hackish implementation of NaCl support. 2763 // We need to notify the valgrind core about 2764 // a) nacl memory range 2765 // b) nacl .nexe file 2766 #include "coregrind/pub_core_clreq.h" 2767 void I_WRAP_SONAME_FNNAME_ZZ(NONE, StopForDebuggerInit) (void *arg); 2768 void I_WRAP_SONAME_FNNAME_ZZ(NONE, StopForDebuggerInit) (void *arg) { 2769 int res; 2770 OrigFn fn; 2771 VALGRIND_GET_ORIG_FN(fn); 2772 CALL_FN_v_W(fn, arg); 2773 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_MEM_START, arg, 0, 0, 0, 0); 2774 } 2775 2776 int I_WRAP_SONAME_FNNAME_ZZ(NONE, GioMemoryFileSnapshotCtor) (void *a, char *file); 2777 int I_WRAP_SONAME_FNNAME_ZZ(NONE, GioMemoryFileSnapshotCtor) (void *a, char *file) { 2778 int res; 2779 OrigFn fn; 2780 int ret; 2781 VALGRIND_GET_ORIG_FN(fn); 2782 CALL_FN_W_WW(ret, fn, a, file); 2783 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_FILE, file, 0, 0, 0, 0); 2784 return ret; 2785 } 2786 2787 //-------------- Functions to Ignore -------------- {{{1 2788 // For some functions we want to ignore everything that happens 2789 // after they were called and before they returned. 2790 // Is there any way that allows to do this via a command line? 2791 #define WRAP_AND_IGNORE(soname, fnname) \ 2792 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *a1, void *a2, void *a3, void *a4); \ 2793 void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *a1, void *a2, void *a3, void *a4) { \ 2794 void* ret; \ 2795 OrigFn fn;\ 2796 VALGRIND_GET_ORIG_FN(fn);\ 2797 IGNORE_ALL_ACCESSES_BEGIN(); \ 2798 CALL_FN_W_WWWW(ret, fn, a1, a2, a3, a4); \ 2799 IGNORE_ALL_ACCESSES_END(); \ 2800 return ret; \ 2801 } 2802 2803 WRAP_AND_IGNORE(NONE, getenv); 2804 2805 // {{{1 end 2806 // vim:shiftwidth=2:softtabstop=2:expandtab 2807