ts_dynamorio.cc revision b32f58018498ea2225959b0ba11c18f0c433deef
1bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov/* Copyright (c) 2008-2010, Google Inc. 2bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * All rights reserved. 3bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 4bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * Redistribution and use in source and binary forms, with or without 5bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * modification, are permitted provided that the following conditions are 6bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * met: 7bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 8bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Redistributions of source code must retain the above copyright 9bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * notice, this list of conditions and the following disclaimer. 10bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Neither the name of Google Inc. nor the names of its 11bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * contributors may be used to endorse or promote products derived from 12bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * this software without specific prior written permission. 13bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 14bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov */ 26bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 27bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// This file is part of ThreadSanitizer, a dynamic data race detector. 28bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 29bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Some parts of the code in this file are taken from the examples 30bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// in DynamoRIO distribution, which have the following copyright. 31bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov/* ********************************************************** 32bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * Copyright (c) 2003-2008 VMware, Inc. All rights reserved. 33bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * **********************************************************/ 34bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 35bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov/* 36bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * Redistribution and use in source and binary forms, with or without 37bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * modification, are permitted provided that the following conditions are met: 38bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 39bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Redistributions of source code must retain the above copyright notice, 40bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * this list of conditions and the following disclaimer. 41bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 42bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Redistributions in binary form must reproduce the above copyright notice, 43bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * this list of conditions and the following disclaimer in the documentation 44bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * and/or other materials provided with the distribution. 45bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 46bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Neither the name of VMware, Inc. nor the names of its contributors may be 47bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * used to endorse or promote products derived from this software without 48bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * specific prior written permission. 49bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 50bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 51bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE 54bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 56bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 57bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 60bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * DAMAGE. 61bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov */ 62bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 63bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Author: Konstantin Serebryany. 64bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Author: Timur Iskhodzhanov. 65bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// 66bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// ******* WARNING ******** 67bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// This code is experimental. Do not expect anything here to work. 68bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// ***** END WARNING ****** 69bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 70bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include "dr_api.h" 71bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 72bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include "ts_util.h" 73bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 74bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#define EXTRA_REPLACE_PARAMS 75bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#define REPORT_READ_RANGE(a,b) 76bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#define REPORT_WRITE_RANGE(a,b) 77bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include "ts_replace.h" 78bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 79bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#define Printf dr_printf 80bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 81bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void *g_lock; 82bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic int g_n_created_threads; 83bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 84bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovtypedef unordered_map<intptr_t, string> SymbolsTable; 85bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic SymbolsTable *sym_tab; 86bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 87bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstring *g_main_module_path; 88bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 89bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//--------------- StackFrame ----------------- {{{1 90bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct StackFrame { 91bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uintptr_t pc; 92bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uintptr_t sp; 93bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov StackFrame(uintptr_t p, uintptr_t s) : pc(p), sp(s) { } 94bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}; 95bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 96bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 97bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//--------------- DrThread ----------------- {{{1 98bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct DrThread { 99bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int tid; // A unique 0-based thread id. 100bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov vector<StackFrame> shadow_stack; 101bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}; 102bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 103bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic DrThread &GetCurrentThread(void *drcontext) { 104bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return *(DrThread*)dr_get_tls_field(drcontext); 105bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 106bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 107bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//--------------- ShadowStack ----------------- {{{1 108bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#define DEB_PR (0 && t.tid == 1) 109bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 110bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void PrintShadowStack(DrThread &t) { 111bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("T%d Shadow stack (%d)\n", t.tid, (int)t.shadow_stack.size()); 112bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (int i = t.shadow_stack.size() - 1; i >= 0; i--) { 113bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uintptr_t pc = t.shadow_stack[i].pc; 114bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("%s[%p]\n", g_main_module_path->c_str(), pc); 115bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 116bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (int i = t.shadow_stack.size() - 1; i >= 0; i--) { 117bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uintptr_t pc = t.shadow_stack[i].pc; 118bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uintptr_t sp = t.shadow_stack[i].sp; 119bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf(" sp=%p pc=%p\n", sp, pc); 120bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 121bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 122bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 123bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void UpdateShadowStack(DrThread &t, uintptr_t sp) { 124bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (t.shadow_stack.size() > 0 && sp >= t.shadow_stack.back().sp) { 125bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov t.shadow_stack.pop_back(); 126bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (DEB_PR) { 127bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_lock(g_lock); 128bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("T%d PopShadowStack\n", t.tid); 129bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PrintShadowStack(t); 130bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_unlock(g_lock); 131bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 132bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 133bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 134bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 135bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void PushShadowStack(DrThread &t, uintptr_t pc, uintptr_t target_pc, uintptr_t sp) { 136bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (t.shadow_stack.size() > 0) { 137bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov t.shadow_stack.back().pc = pc; 138bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 139bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov t.shadow_stack.push_back(StackFrame(target_pc, sp)); 140bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (DEB_PR) { 141bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_lock(g_lock); 142bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("T%d PushShadowStack %p %p %d\n", t.tid, pc, target_pc, sp); 143bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PrintShadowStack(t); 144bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_unlock(g_lock); 145bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 146bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 147bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 148bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//--------------- callbacks ----------------- {{{1 149bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void OnEvent_ThreadInit(void *drcontext) { 150bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DrThread *t_ptr = new DrThread; 151bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DrThread &t = *t_ptr; 152bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 153bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_lock(g_lock); 154bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov t.tid = g_n_created_threads++; 155bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_unlock(g_lock); 156bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 157bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_set_tls_field(drcontext, t_ptr); 158bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 159bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("T%d %s\n", t.tid, (char*)__FUNCTION__+8); 160bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 161bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 162bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void OnEvent_ThreadExit(void *drcontext) { 163bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DrThread &t = GetCurrentThread(drcontext); 164bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("T%d %s\n", t.tid, (char*)__FUNCTION__+8); 165bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 166bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 167bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid OnEvent_ModuleLoaded(void *drcontext, const module_data_t *info, 168bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov bool loaded) { 169bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // if this assertion fails, your DynamoRIO is too old. You need rev261 with some patches... 170bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(info->full_path); 171bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 172bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("%s: %s (%s)\n", __FUNCTION__, 173bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_module_preferred_name(info), info->full_path); 174bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (g_main_module_path == NULL) { 175bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov g_main_module_path = new string(info->full_path); 176bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 177bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 178bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 179bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void OnEvent_Exit(void) { 180bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("ThreadSanitizerDynamoRio: done\n"); 181bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_mutex_destroy(g_lock); 182bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 183bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 184bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_Mop(uintptr_t pc, size_t size, void *a, bool is_w) { 185bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov void *drcontext = dr_get_current_drcontext(); 186bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DrThread &t = GetCurrentThread(drcontext); 187bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (t.tid == 777) { 188bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_fprintf(STDERR, "T%d pc=%p a=%p size=%ld %s\n", t.tid, pc, a, size, is_w ? "WRITE" : "READ"); 189bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 190bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 191bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 192bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_Read(uintptr_t pc, size_t size, void *a) { 193bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov On_Mop(pc, size, a, false); 194bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 195bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 196bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_Write(uintptr_t pc, size_t size, void *a) { 197bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov On_Mop(pc, size, a, true); 198bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 199bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 200bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_AnyCall(uintptr_t pc, uintptr_t target_pc, uintptr_t sp, bool is_direct) { 201bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov void *drcontext = dr_get_current_drcontext(); 202bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DrThread &t = GetCurrentThread(drcontext); 203bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // dr_fprintf(STDOUT, "T%d CALL %p => %p; sp=%p\n", t.tid, pc, target_pc, sp); 204bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PushShadowStack(t, pc, target_pc, sp); 205bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 206bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 207bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_DirectCall(uintptr_t pc, uintptr_t target_pc, uintptr_t sp) { 208bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov On_AnyCall(pc, target_pc, sp, true); 209bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 210bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 211bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_IndirectCall(uintptr_t pc, uintptr_t target_pc, uintptr_t sp) { 212bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov On_AnyCall(pc, target_pc, sp, false); 213bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 214bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 215bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void On_TraceEnter(uintptr_t pc, uintptr_t sp) { 216bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov void *drcontext = dr_get_current_drcontext(); 217bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DrThread &t = GetCurrentThread(drcontext); 218bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // dr_fprintf(STDOUT, "T%d TRACE:\n%p\n%p\n", t.tid, pc, sp); 219bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov UpdateShadowStack(t, sp); 220bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 221bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 222bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//--------------- instrumentation ----------------- {{{1 223bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovopnd_t opnd_create_base_disp_from_dst(opnd_t dst) { 224bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return opnd_create_base_disp(opnd_get_base(dst), 225bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_get_index(dst), 226bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_get_scale(dst), 227bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_get_disp(dst), 228bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov OPSZ_lea); 229bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 230bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 231bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void InstrumentOneMop(void* drcontext, instrlist_t *bb, 232bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *instr, opnd_t opnd, bool is_w) { 233bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // opnd_disassemble(drcontext, opnd, 1); 234bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // dr_printf(" -- (%s opnd)\n", is_w ? "write" : "read"); 235bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov void *callback = (void*)(is_w ? On_Write : On_Read); 236bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int size = opnd_size_in_bytes(opnd_get_size(opnd)); 237bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 238bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *tmp_instr = NULL; 239bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov reg_id_t reg = REG_XAX; 240bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 241bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov /* save %xax */ 242bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_save_reg(drcontext, bb, instr, reg, SPILL_SLOT_2); 243bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 244bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (opnd_is_base_disp(opnd)) { 245bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov /* lea opnd => %xax */ 246bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_set_size(&opnd, OPSZ_lea); 247bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov tmp_instr = INSTR_CREATE_lea(drcontext, 248bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_create_reg(reg), 249bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd); 250bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else if( 251bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#ifdef X86_64 252bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_is_rel_addr(opnd) || 253bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#endif 254bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_is_abs_addr(opnd)) { 255bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov tmp_instr = INSTR_CREATE_mov_imm(drcontext, 256bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_create_reg(reg), 257bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov OPND_CREATE_INTPTR(opnd_get_addr(opnd))); 258bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 259bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (tmp_instr) { 260bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // CHECK(tmp_instr); 261bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_meta_preinsert(bb, instr, tmp_instr); 262bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 263bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov /* clean call */ 264bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_insert_clean_call(drcontext, bb, instr, callback, false, 265bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 3, 266bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov OPND_CREATE_INTPTR(instr_get_app_pc(instr)), 267bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov OPND_CREATE_INT32(size), 268bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_create_reg(reg)); 269bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov /* restore %xax */ 270bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_restore_reg(drcontext, bb, instr, REG_XAX, SPILL_SLOT_2); 271bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else { 272bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("%s ????????????????????\n", __FUNCTION__); 273bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 274bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 275bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 276bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void InstrumentMopInstruction(void *drcontext, 277bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_t *bb, instr_t *instr) { 278bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // reads: 279bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (int a = 0; a < instr_num_srcs(instr); a++) { 280bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_t curop = instr_get_src(instr, a); 281bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (opnd_is_memory_reference(curop)) { 282bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov InstrumentOneMop(drcontext, bb, instr, curop, false); 283bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 284bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 285bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // writes: 286bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (int a = 0; a < instr_num_dsts(instr); a++) { 287bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_t curop = instr_get_dst(instr, a); 288bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (opnd_is_memory_reference(curop)) { 289bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov InstrumentOneMop(drcontext, bb, instr, curop, true); 290bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 291bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 292bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov //dr_printf("reads: %d writes: %d\n", n_reads, n_writes); 293bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 294bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 295bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void InstrumentInstruction(void *drcontext, instrlist_t *bb, 296bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *instr) { 297bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // instr_disassemble(drcontext, instr, 1); 298bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // dr_printf(" -- \n"); 299bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (instr_is_call_direct(instr)) { 300bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_insert_call_instrumentation(drcontext, bb, instr, 301bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (app_pc)On_DirectCall); 302bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else if (instr_is_call_indirect(instr)) { 303bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_insert_mbr_instrumentation(drcontext, bb, instr, 304bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (app_pc)On_IndirectCall, SPILL_SLOT_1); 305bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 306bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else if (instr_reads_memory(instr) || instr_writes_memory(instr)) { 307bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov InstrumentMopInstruction(drcontext, bb, instr); 308bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 309bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 310bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 311bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic dr_emit_flags_t OnEvent_Trace(void *drcontext, void *tag, 312bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_t *trace, bool translating) { 313bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *first_instr = NULL; 314bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (instr_t *instr = instrlist_first(trace); instr != NULL; 315bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr = instr_get_next(instr)) { 316bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (instr_get_app_pc(instr)) { 317bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov first_instr = instr; 318bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 319bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 320bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 321bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (first_instr) { 322bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // instr_disassemble(drcontext, first_instr, 1); 323bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // dr_printf(" -- in_trace %p\n", instr_get_app_pc(first_instr)); 324bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_insert_clean_call(drcontext, trace, first_instr, 325bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (void*)On_TraceEnter, false, 326bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 2, 327bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov OPND_CREATE_INTPTR(instr_get_app_pc(first_instr)), 328bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_create_reg(REG_XSP) 329bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ); 330bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 331bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return DR_EMIT_DEFAULT; 332bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 333bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 334bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint replace_foo(int i, int j, int k) { 335bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf(" dy 'foo_replace'(%i, %i, %i)\n", i, j, k); 336bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return 1; 337bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 338bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 339bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovtypedef unordered_map<intptr_t, void*> FunctionsReplaceMap; 340bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic FunctionsReplaceMap *fun_replace_map; 341bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 342bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovnamespace wrap { 343bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 344bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint (*orig_foo)(int,int,int) = NULL; 345bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint in_wrapper = 0; // TODO: Make it thread-local 346bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 347bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic int wrapped_foo(int i, int j, int k) { 348bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov in_wrapper = 1; 349bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 350bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf(" dy 'foo_wrap'(%i, %i, %i)\n", i, j, k); 351bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("orig_foo = %p\n", orig_foo); 352bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int ret = 13; 353bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (orig_foo != NULL) 354bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ret = orig_foo(i, j, k) + 4200; 355bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov else 356bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("ERROR! orig_foo is not set!\n");/**/ 357bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 358bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov in_wrapper = 0; 359bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return ret; 360bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 361bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 362bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint is_in_wrapper(int arg) { 363bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // TODO: this may not work well with recursive functions 364bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return in_wrapper; 365bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 366bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 367bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 368bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid print_bb(void* drcontext, instrlist_t *bb, const char * desc) { 369bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("==================\n"); 370bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("%s:\n", desc); 371bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (instr_t *i = instrlist_first(bb); i != NULL; i = instr_get_next(i)) { 372bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_disassemble(drcontext, i, 1); 373bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("\n"); 374bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 375bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("==================\n"); 376bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 377bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 378bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic dr_emit_flags_t OnEvent_BB(void* drcontext, void *tag, instrlist_t *bb, 379bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov bool for_trace, bool translating) { 380bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *first_instr = instrlist_first(bb); 381bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov app_pc pc = instr_get_app_pc(first_instr); 382bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string symbol_name = "UNKNOWN"; 383bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (sym_tab->find((intptr_t)pc) != sym_tab->end()) { 384bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov symbol_name = (*sym_tab)[(intptr_t)pc]; 385bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov //dr_printf("Symbol = %s\n", symbol_name.c_str()); 386bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 387bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 388bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (fun_replace_map->count((intptr_t)pc) > 0) { 389bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // Replace client function with the function supplied by the tool. 390bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // The logic is inspired by drmemory/replace.c 391bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov app_pc target_fun = (app_pc)(*fun_replace_map)[(intptr_t)pc]; 392bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov const module_data_t *info = dr_lookup_module(pc); 393bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("REDIR: %s (from %s) redirected to %p\n", 394bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov symbol_name.c_str(), info->full_path, target_fun); 395bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 396bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_clear(drcontext, bb); 397bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_append(bb, INSTR_XL8(INSTR_CREATE_jmp(drcontext, opnd_create_pc(target_fun)), pc)); 398bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else { 399bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (StringMatch("*foo_to_wrap*", symbol_name)) { 400bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov const module_data_t *info = dr_lookup_module(pc); 401bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf(" 'foo_to_wrap' entry point: bb %p, %s / %s\n", pc, dr_module_preferred_name(info), info->full_path); 402bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov wrap::orig_foo = (int (*)(int,int,int))(void*)pc; 403bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 404bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov //print_bb(drcontext, bb, "BEFORE"); 405bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // TODO: Use something more optimized than clean_call 406bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_insert_clean_call(drcontext, bb, first_instr, (void*)wrap::is_in_wrapper, 407bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov false, 1, OPND_CREATE_INTPTR(pc)); 408bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *opr_instr = INSTR_CREATE_test(drcontext, opnd_create_reg(REG_XAX), 409bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_create_reg(REG_XAX)); 410bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *jne_instr = INSTR_CREATE_jcc(drcontext, OP_jz, 411bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov opnd_create_pc((app_pc)wrap::wrapped_foo)); 412bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_meta_preinsert(bb, first_instr, opr_instr); 413bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instrlist_meta_preinsert(bb, first_instr, jne_instr); 414bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 415bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov //print_bb(drcontext, bb, "AFTER"); 416bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 417bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 418bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov instr_t *instr, *next_instr; 419bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) { 420bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov next_instr = instr_get_next(instr); 421bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (instr_get_app_pc(instr)) // don't instrument non-app code 422bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov InstrumentInstruction(drcontext, bb, instr); 423bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 424bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 425bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 426bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov OnEvent_Trace(drcontext, tag, bb, translating); 427bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 428bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 429bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return DR_EMIT_DEFAULT; 430bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 431bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 432bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid ReadSymbolsTableFromFile(const char *filename) { 433bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov file_t f = dr_open_file(filename, DR_FILE_READ); 434bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(f != INVALID_FILE); 435bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 436bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov const int BUFF_SIZE = 1 << 16; // should be enough for testing 437bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char buff[BUFF_SIZE]; 438bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_read_file(f, buff, BUFF_SIZE); 439bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char *cur_line = buff; 440bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (*cur_line) { 441bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char *next_line = strstr(cur_line, "\n"); 442bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (next_line != NULL) 443bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *next_line = 0; 444bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char fun_name[1024]; 445bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char dummy; 446bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov void* pc; 447bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov sscanf(cur_line, "%p %c %s", &pc, &dummy, fun_name); 448bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov //dr_printf("%s => %p\n", fun_name, pc); 449bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (*sym_tab)[(intptr_t)pc] = fun_name; 450bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 451bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (next_line == NULL) break; 452bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov cur_line = next_line + 1; 453bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 454bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 455bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 456bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 457bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid ReplaceFunc3(void *img, void *rtn, string filter, void *fun_ptr) { 458bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (SymbolsTable::iterator i = sym_tab->begin(); i != sym_tab->end(); i++) { 459bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (StringMatch(filter, i->second)) 460bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (*fun_replace_map)[(intptr_t)i->first] = fun_ptr; 461bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 462bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 463bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 464bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//--------------- dr_init ----------------- {{{1 465bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy StepanovDR_EXPORT void dr_init(client_id_t id) { 466bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov sym_tab = new SymbolsTable; 467bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 468bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // HACK doesn't work if multiple options are passed. 469bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov const char *opstr = dr_get_options(id); 470bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_printf("Options: %s\n", opstr); 471bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov const char *fname = strstr(opstr, "--symbols="); 472bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (fname) { 473bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReadSymbolsTableFromFile(fname + 10); 474bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 475bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 476bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // Register events. 477bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_register_exit_event(OnEvent_Exit); 478bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_register_bb_event(OnEvent_BB); 479bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_register_trace_event(OnEvent_Trace); 480bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_register_thread_init_event(OnEvent_ThreadInit); 481bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_register_thread_exit_event(OnEvent_ThreadExit); 482bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov dr_register_module_load_event(OnEvent_ModuleLoaded); 483bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov g_lock = dr_mutex_create(); 484bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 485bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov fun_replace_map = new FunctionsReplaceMap(); 486bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov void *img = NULL, *rtn = NULL; 487bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov #define AFUNPTR void* 488bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "memchr", (AFUNPTR)Replace_memchr); 489bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "strchr", (AFUNPTR)Replace_strchr); 490bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "index", (AFUNPTR)Replace_strchr); 491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "strchrnul", (AFUNPTR)Replace_strchrnul); 492bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "strrchr", (AFUNPTR)Replace_strrchr); 493bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "rindex", (AFUNPTR)Replace_strrchr); 494bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "strlen", (AFUNPTR)Replace_strlen); 495bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "memcpy", (AFUNPTR)Replace_memcpy); 496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "memmove", (AFUNPTR)Replace_memmove); 497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "memcmp", (AFUNPTR)Replace_memcmp); 498bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "strcpy", (AFUNPTR)Replace_strcpy); 499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "stpcpy", (AFUNPTR)Replace_stpcpy); 500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "strncpy", (AFUNPTR)Replace_strncpy); 501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "strcmp", (AFUNPTR)Replace_strcmp); 502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "strncmp", (AFUNPTR)Replace_strncmp); 503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ReplaceFunc3(img, rtn, "strcat", (AFUNPTR)Replace_strcat); 504bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReplaceFunc3(img, rtn, "*foo_to_replace*", (AFUNPTR)replace_foo); 505bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 506bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// end. {{{1 507bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// vim:shiftwidth=2:softtabstop=2:expandtab 508