1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Client-space code for drd. drd_qtcore_intercepts.c ---*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of drd, a thread error detector. 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown These functions are not called directly - they're the targets of code 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirection or load notifications (see pub_core_redir.h for info). 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown They're named weirdly so that the intercept code can find them when the 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shared object is initially loaded. 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that this filename has the "drd_" prefix because it can appear 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in stack traces, and the "drd_" makes it a little clearer that it 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown originates from Valgrind. 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h> 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_clientreq.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_redir.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Defines. 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define QT4CORE_FUNC(ret_ty, f, args...) \ 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args); \ 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args) 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////// 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex intercepts. 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////////// 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum { qt_nonrecursive = 0, qt_recursive = 1 } qt_mutex_mode; 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Convert a Qt4 mutex type to a DRD mutex type. */ 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic MutexT qt_to_drd_mutex_type(qt_mutex_mode mode) 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (mode) 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case qt_nonrecursive: 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mutex_type_default_mutex; 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case qt_recursive: 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mutex_type_recursive_mutex; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mutex_type_invalid_mutex; 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Find out the type of a Qt4 mutex (recursive or not). 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Since it's not possible to do this in a portable way, return 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * mutex_type_unknown and let drd_mutex.c look up the real mutex type. 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic MutexT mutex_type(void* qt4_mutex) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mutex_type_unknown; 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::QMutex(RecursionMode) -- _ZN6QMutexC1ENS_13RecursionModeE, 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(void, _ZN6QMutexC1ENS_13RecursionModeE, 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex, 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qt_mutex_mode mode) 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT, 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, mutex, mode); 96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT, 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, 0, 0, 0, 0); 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::QMutex(RecursionMode) -- _ZN6QMutexC2ENS_13RecursionModeE 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(void, _ZN6QMutexC2ENS_13RecursionModeE, 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex, 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qt_mutex_mode mode) 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT, 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, mutex, mode); 111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT, 112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, 0, 0, 0, 0); 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::~QMutex() -- _ZN6QMutexD1Ev 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(void, _ZN6QMutexD1Ev, 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex) 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY, 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, 0, 0, 0, 0); 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY, 126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, mutex_type(mutex), 0, 0, 0); 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::~QMutex() -- _ZN6QMutexD2Ev 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(void, _ZN6QMutexD2Ev, 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void** mutex) 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY, 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, 0, 0, 0, 0); 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY, 140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, mutex_type(mutex), 0, 0, 0); 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::lock() -- _ZN6QMutex4lockEv 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(void, _ZN6QMutex4lockEv, 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex) 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, mutex_type(mutex), 0, 0, 0); 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, 1, 0, 0, 0); 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::tryLock() -- _ZN6QMutex7tryLockEv 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(int, _ZN6QMutex7tryLockEv, 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex) 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, mutex_type(mutex), 1, 0, 0); 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, ret, 0, 0, 0); 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::tryLock(int) -- _ZN6QMutex7tryLockEi 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(int, _ZN6QMutex7tryLockEi, 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex, 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int timeout_ms) 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, mutex_type(mutex), 1, 0, 0); 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, mutex, timeout_ms); 183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, ret, 0, 0, 0); 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::unlock() -- _ZN6QMutex6unlockEv 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4CORE_FUNC(void, _ZN6QMutex6unlockEv, 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex) 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK, 196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, mutex_type(mutex), 0, 0, 0); 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK, 199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mutex, 0, 0, 0, 0); 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 201