1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Function replacement and wrapping. m_redir.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2000-2013 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2003-2013 Jeremy Fitzhardinge 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jeremy@goop.org 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_vki.h" 40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_libcfile.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_seqmatch.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_oset.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h" 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" // VG_(needs).malloc_replacement 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" // VG_(fnptr_to_fnentry) 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" // VG_(am_find_nsegment) 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" // VG_(client___libc_freeres_wrapper) 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_demangle.h" // VG_(maybe_Z_demangle) 54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_libcproc.h" // VG_(libdir) 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h" /* GLIBC_2_* */ 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This module is a critical part of the redirection/intercept system. 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It keeps track of the current intercept state, cleans up the 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation caches when that state changes, and finally, answers 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queries about the whether an address is currently redirected or 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not. It doesn't do any of the control-flow trickery needed to put 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the redirections into practice. That is the job of m_translate, 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which calls here to find out which translations need to be 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirected. 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The interface is simple. VG_(redir_initialise) initialises and 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loads some hardwired redirects which never disappear; this is 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform-specific. 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The module is notified of redirection state changes by m_debuginfo. 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That calls VG_(redir_notify_new_DebugInfo) when a new DebugInfo 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (shared object symbol table, basically) appears. Appearance of new 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols can cause new (active) redirections to appear for two 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reasons: the symbols in the new table may match existing 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirection specifications (see comments below), and because the 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols in the new table may themselves supply new redirect 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specifications which match existing symbols (or ones in the new 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown table). 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Redirect specifications are really symbols with "funny" prefixes 83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (_vgrNNNNZU_ and _vgrNNNNZZ_). These names tell m_redir that the 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown associated code should replace the standard entry point for some 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set of functions. The set of functions is specified by a (soname 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pattern, function name pattern) pair which is encoded in the symbol 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name following the prefix. The names use a Z-encoding scheme so 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that they may contain punctuation characters and wildcards (*). 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The encoding scheme is described in pub_tool_redir.h and is decoded 90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov by VG_(maybe_Z_demangle). The NNNN are behavioural equivalence 91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov class tags, and are used to by code in this module to resolve 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov situations where one address appears to be redirected to more than 93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov one replacement/wrapper. This is also described in 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pub_tool_redir.h. 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a shared object is unloaded, this module learns of it via a 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call to VG_(redir_notify_delete_DebugInfo). It then removes from 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown its tables all active redirections in any way associated with that 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object, and tidies up the translation caches accordingly. 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That takes care of tracking the redirection state. When a 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation is actually to be made, m_translate calls to 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_do_lookup) in this module to find out if the 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation's address should be redirected. 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Semantics ---*/ 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The redirector holds two pieces of state: 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specs - a set of (soname pattern, fnname pattern) -> redir addr 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active - a set of orig addr -> (bool, redir addr) 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active is the currently active set of bindings that the translator 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown consults. Specs is the current set of specifications as harvested 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from reading symbol tables of the currently loaded objects. 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active is a pure function of Specs and the current symbol table 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state (maintained by m_debuginfo). Call the latter SyminfoState. 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Therefore whenever either Specs or SyminfoState changes, Active 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown must be recomputed. [Inefficient if done naively, but this is a 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec]. 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active is computed as follows: 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active = empty 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for spec in Specs { 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sopatt = spec.soname pattern 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnpatt = spec.fnname pattern 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redir = spec.redir addr 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for so matching sopatt in SyminfoState { 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for fn matching fnpatt in fnnames_of(so) { 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &fn -> redir is added to Active 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [as an implementation detail, when a binding (orig -> redir) is 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deleted from Active as a result of recomputing it, then all 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translations intersecting redir must be deleted. However, this is 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not part of the spec]. 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [Active also depends on where the aspacemgr has decided to put all 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the pieces of code -- that affects the "orig addr" and "redir addr" 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown values.] 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --------------------- 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That completes the spec, apart from one difficult issue: duplicates. 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Clearly we must impose the requirement that domain(Active) contains 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown no duplicates. The difficulty is how to constrain Specs enough to 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown avoid getting into that situation. It's easy to write specs which 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown could cause conflicting bindings in Active, eg: 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_mutex_lock) -> a1 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_*) -> a2 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for a1 != a2. Or even hairier: 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_mutex_*) -> a1 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_*_lock) -> a2 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I can't think of any sane way of detecting when an addition to 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specs would generate conflicts. However, considering we don't 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actually want to have a system that allows this, I propose this: 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all changes to Specs are acceptable. But, when recomputing Active 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown following the change, if the same orig is bound to more than one 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redir, then the first binding for orig is retained, and all the 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rest ignored. 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown =========================================================== 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown =========================================================== 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Incremental implementation: 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a new DebugInfo appears: 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - it may be the source of new specs 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - it may be the source of new matches for existing specs 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Therefore: 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (new Specs x existing DebugInfos): scan all symbols in the new 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo to find new specs. Each of these needs to be compared 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown against all symbols in all the existing DebugInfos to generate 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new actives. 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (existing Specs x new DebugInfo): scan all symbols in the 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo, trying to match them to any existing specs, also 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generating new actives. 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (new Specs x new DebugInfo): scan all symbols in the new 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo, trying to match them against the new specs, to 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate new actives. 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Finally, add new new specs to the current set of specs. 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When adding a new active (s,d) to the Actives: 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookup s in Actives 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if already bound to d, ignore 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if already bound to something other than d, complain loudly and ignore 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else add (s,d) to Actives 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and discard (s,1) and (d,1) (maybe overly conservative) 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a DebugInfo disappears: 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - delete all specs acquired from the seginfo 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - delete all actives derived from the just-deleted specs 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if each active (s,d) deleted, discard (s,1) and (d,1) 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- REDIRECTION SPECIFICATIONS ---*/ 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A specification of a redirection we want to do. Note that because 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both the "from" soname and function name may contain wildcards, the 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec can match an arbitrary number of times. 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16 Nov 2007: Comments re .mandatory field: The initial motivation 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for this is making Memcheck work sanely on glibc-2.6.X ppc32-linux. 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We really need to intercept 'strlen' in ld.so right from startup. 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If ld.so does not have a visible 'strlen' symbol, Memcheck 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generates an impossible number of errors resulting from highly 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tuned strlen implementation in ld.so, and is completely unusable 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -- the resulting undefinedness eventually seeps everywhere. */ 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _Spec { 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _Spec* next; /* linked list */ 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXED PARTS -- set when created and not changed */ 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* from_sopatt; /* from soname pattern */ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* from_fnpatt; /* from fnname pattern */ 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr to_addr; /* where redirecting to */ 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isWrap; /* wrap or replacement? */ 236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int becTag; /* 0 through 9999. Behavioural equivalance class tag. 237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov If two wrappers have the same (non-zero) tag, they 238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov are promising that they behave identically. */ 239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int becPrio; /* 0 through 9. Behavioural equivalence class prio. 240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Used to choose between competing wrappers with 241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the same (non-zero) tag. */ 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar** mandatory; /* non-NULL ==> abort V and print the 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strings if from_sopatt is loaded but 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from_fnpatt cannot be found */ 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VARIABLE PARTS -- used transiently whilst processing redirections */ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool mark; /* set if spec requires further processing */ 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool done; /* set if spec was successfully matched */ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec; 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Top-level data structure. It contains a pointer to a DebugInfo and 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown also a list of the specs harvested from that DebugInfo. Note that 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seginfo is allowed to be NULL, meaning that the specs are 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre-loaded ones at startup and are not associated with any 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown particular seginfo. */ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _TopSpec { 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _TopSpec* next; /* linked list */ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* seginfo; /* symbols etc */ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specs; /* specs pulled out of seginfo */ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool mark; /* transient temporary used during deletion */ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec; 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the top level list of redirections. m_debuginfo maintains 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a list of DebugInfos, and the idea here is to maintain a list with 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same number of elements (in fact, with one more element, so as 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to record abovementioned preloaded specifications.) */ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TopSpec* topSpecs = NULL; 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- CURRENTLY ACTIVE REDIRECTIONS ---*/ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Represents a currently active binding. If either parent_spec or 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parent_sym is NULL, then this binding was hardwired at startup and 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should not be deleted. Same is true if either parent's seginfo 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown field is NULL. */ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr from_addr; /* old addr -- MUST BE THE FIRST WORD! */ 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr to_addr; /* where redirecting to */ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_spec; /* the TopSpec which supplied the Spec */ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_sym; /* the TopSpec which supplied the symbol */ 286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int becTag; /* behavioural eclass tag for ::to_addr */ 287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int becPrio; /* and its priority */ 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isWrap; /* wrap or replacement? */ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isIFunc; /* indirect function? */ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The active set is a fast lookup table */ 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OSet* activeSet = NULL; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Wrapper routine for indirect functions */ 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr iFuncWrapper; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- FWDses ---*/ 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void maybe_add_active ( Active /*by value; callee copies*/ ); 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void* dinfo_zalloc(const HChar* ec, SizeT); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void dinfo_free(void*); 307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* dinfo_strdup(const HChar* ec, const HChar*); 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_plausible_guest_addr(Addr); 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_redir_state ( const HChar* who ); 311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_active ( const HChar* left, Active* act ); 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void handle_maybe_load_notifier( const HChar* soname, 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* symbol, Addr addr ); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_require_text_symbols ( DebugInfo* ); 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NOTIFICATIONS ---*/ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid generate_and_add_actives ( 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* spec list and the owning TopSpec */ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specs, 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_spec, 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* debuginfo and the owning TopSpec */ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di, 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_sym 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Copy all the names from a given symbol into an AR_DINFO allocated, 334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NULL terminated array, for easy iteration. Caller must pass also 335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the address of a 2-entry array which can be used in the common case 336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to avoid dynamic allocation. */ 337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar** alloc_symname_array ( HChar* pri_name, HChar** sec_names, 338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** twoslots ) 339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Special-case the common case: only one name. We expect the 341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov caller to supply a stack-allocated 2-entry array for this. */ 342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sec_names == NULL) { 343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov twoslots[0] = pri_name; 344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov twoslots[1] = NULL; 345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return twoslots; 346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Else must use dynamic allocation. Figure out size .. */ 348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word n_req = 1; 349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** pp = sec_names; 350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (*pp) { n_req++; pp++; } 351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* .. allocate and copy in. */ 352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** arr = dinfo_zalloc( "redir.asa.1", (n_req+1) * sizeof(HChar*) ); 353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word i = 0; 354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arr[i++] = pri_name; 355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pp = sec_names; 356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (*pp) { arr[i++] = *pp; pp++; } 357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(i == n_req); 358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(arr[n_req] == NULL); 359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return arr; 360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Free the array allocated by alloc_symname_array, if any. */ 364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void free_symname_array ( HChar** names, HChar** twoslots ) 365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (names != twoslots) 367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov dinfo_free(names); 368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HChar const* advance_to_equal ( HChar const* c ) { 371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng while (*c && *c != '=') { 372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ++c; 373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return c; 375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HChar const* advance_to_comma ( HChar const* c ) { 377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng while (*c && *c != ',') { 378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ++c; 379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return c; 381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notify m_redir of the arrival of a new DebugInfo. This is fairly 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complex, but the net effect is to (1) add a new entry to the 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topspecs list, and (2) figure out what new binding are now active, 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and, as a result, add them to the actives mapping. */ 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_DEMANGLED 256 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_(redir_notify_new_DebugInfo)( DebugInfo* newdi ) 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok, isWrap; 393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int i, nsyms, becTag, becPrio; 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specList; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* spec; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* ts; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* newts; 398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* sym_name_pri; 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** sym_names_sec; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sym_addr, sym_toc; 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar demangled_sopatt[N_DEMANGLED]; 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar demangled_fnpatt[N_DEMANGLED]; 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool check_ppcTOCs = False; 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isText; 405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* newdi_soname; 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_PLAT_USES_PPCTOC) 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_ppcTOCs = True; 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(newdi); 412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov newdi_soname = VG_(DebugInfo_get_soname)(newdi); 413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(newdi_soname != NULL); 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#ifdef ENABLE_INNER 416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* When an outer Valgrind is executing an inner Valgrind, the 418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng inner "sees" in its address space the mmap-ed vgpreload files 419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng of the outer. The inner must avoid interpreting the 420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng redirections given in the outer vgpreload mmap-ed files. 421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Otherwise, some tool combinations badly fail. 422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Example: outer memcheck tool executing an inner none tool. 424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng If inner none interprets the outer malloc redirection, the 426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng inner will redirect malloc to a memcheck function it does not 427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng have (as the redirection target is from the outer). With 428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng such a failed redirection, a call to malloc inside the inner 429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng will then result in a "no-operation" (and so no memory will 430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng be allocated). 431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng When running as an inner, no redirection will be done 433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for a vgpreload file if this file is not located in the 434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng inner VALGRIND_LIB directory. 435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Recognising a vgpreload file based on a filename pattern 437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is a kludge. An alternate solution would be to change 438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the _vgr prefix according to outer/inner/client. 439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */ 440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* newdi_filename = VG_(DebugInfo_get_filename)(newdi); 441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* newdi_basename = VG_(basename) (newdi_filename); 442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(strncmp) (newdi_basename, "vgpreload_", 10) == 0) { 443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* This looks like a vgpreload file => check if this file 444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is from the inner VALGRIND_LIB. 445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng We do this check using VG_(stat) + dev/inode comparison 446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as vg-in-place defines a VALGRIND_LIB with symlinks 447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng pointing to files inside the valgrind build directories. */ 448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct vg_stat newdi_stat; 449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng SysRes newdi_res; 450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar in_vglib_filename[VKI_PATH_MAX]; 451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng struct vg_stat in_vglib_stat; 452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng SysRes in_vglib_res; 453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng newdi_res = VG_(stat)(newdi_filename, &newdi_stat); 455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(strncpy) (in_vglib_filename, VG_(libdir), VKI_PATH_MAX); 457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(strncat) (in_vglib_filename, "/", VKI_PATH_MAX); 458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(strncat) (in_vglib_filename, newdi_basename, VKI_PATH_MAX); 459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng in_vglib_res = VG_(stat)(in_vglib_filename, &in_vglib_stat); 460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* If we find newdi_basename in inner VALGRIND_LIB 462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng but newdi_filename is not the same file, then we do 463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng not execute the redirection. */ 464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (!sr_isError(in_vglib_res) 465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && !sr_isError(newdi_res) 466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && (newdi_stat.dev != in_vglib_stat.dev 467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || newdi_stat.ino != in_vglib_stat.ino)) { 468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* <inner VALGRIND_LIB>/newdi_basename is an existing file 469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng and is different of newdi_filename. 470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng So, we do not execute newdi_filename redirection. */ 471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if ( VG_(clo_verbosity) > 1 ) { 472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)( Vg_DebugMsg, 473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "Skipping vgpreload redir in %s" 474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " (not from VALGRIND_LIB_INNER)\n", 475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng newdi_filename); 476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if ( VG_(clo_verbosity) > 1 ) { 480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)( Vg_DebugMsg, 481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "Executing vgpreload redir in %s" 482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " (from VALGRIND_LIB_INNER)\n", 483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng newdi_filename); 484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif 489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stay sane: we don't already have this. */ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) 493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(ts->seginfo != newdi); 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* scan this DebugInfo's symbol table, pulling out and demangling 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any specs found */ 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specList = NULL; /* the spec list we're building up */ 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov nsyms = VG_(DebugInfo_syms_howmany)( newdi ); 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nsyms; i++) { 502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(DebugInfo_syms_getidx)( newdi, i, &sym_addr, &sym_toc, 503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NULL, &sym_name_pri, &sym_names_sec, 504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &isText, NULL ); 505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Set up to conveniently iterate over all names for this symbol. */ 506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* twoslots[2]; 507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec, 508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &twoslots[0]); 509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names; 510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (names = names_init; *names; names++) { 511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ok = VG_(maybe_Z_demangle)( *names, 512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov demangled_sopatt, N_DEMANGLED, 513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov demangled_fnpatt, N_DEMANGLED, 514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &isWrap, &becTag, &becPrio ); 515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* ignore data symbols */ 516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!isText) 517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!ok) { 519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* It's not a full-scale redirect, but perhaps it is a load-notify 520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn? Let the load-notify department see it. */ 521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov handle_maybe_load_notifier( newdi_soname, *names, sym_addr ); 522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (check_ppcTOCs && sym_toc == 0) { 525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* This platform uses toc pointers, but none could be found 526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for this symbol, so we can't safely redirect/wrap to it. 527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Just skip it; we'll make a second pass over the symbols in 528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the following loop, and complain at that point. */ 529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0 == VG_(strncmp) (demangled_sopatt, 533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_SO_SYN_PREFIX, VG_SO_SYN_PREFIX_LEN)) { 534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* This is a redirection for handling lib so synonyms. If we 535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng have a matching lib synonym, then replace the sopatt. 536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Otherwise, just ignore this redirection spec. */ 537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (!VG_(clo_soname_synonyms)) 539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng continue; // No synonyms => skip the redir. 540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Search for a matching synonym=newname*/ 542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng SizeT const sopatt_syn_len 543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = VG_(strlen)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN); 544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HChar const* last = VG_(clo_soname_synonyms); 545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng while (*last) { 547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HChar const* first = last; 548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng last = advance_to_equal(first); 549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if ((last - first) == sopatt_syn_len 551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && 0 == VG_(strncmp)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN, 552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng first, 553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sopatt_syn_len)) { 554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Found the demangle_sopatt synonym => replace it 555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng first = last + 1; 556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng last = advance_to_comma(first); 557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(strncpy)(demangled_sopatt, first, last - first); 558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng demangled_sopatt[last - first] = '\0'; 559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng last = advance_to_comma(last); 563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (*last == ',') 564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng last++; 565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // If we have not replaced the sopatt, then skip the redir. 568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0 == VG_(strncmp) (demangled_sopatt, 569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_SO_SYN_PREFIX, VG_SO_SYN_PREFIX_LEN)) 570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng continue; 571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec = dinfo_zalloc("redir.rnnD.1", sizeof(Spec)); 574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(spec); 575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->from_sopatt = dinfo_strdup("redir.rnnD.2", demangled_sopatt); 576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->from_fnpatt = dinfo_strdup("redir.rnnD.3", demangled_fnpatt); 577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(spec->from_sopatt); 578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(spec->from_fnpatt); 579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->to_addr = sym_addr; 580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->isWrap = isWrap; 581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->becTag = becTag; 582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->becPrio = becPrio; 583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* check we're not adding manifestly stupid destinations */ 584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(is_plausible_guest_addr(sym_addr)); 585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->next = specList; 586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->mark = False; /* not significant */ 587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->done = False; /* not significant */ 588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov specList = spec; 5899bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root } 590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free_symname_array(names_init, &twoslots[0]); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (check_ppcTOCs) { 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nsyms; i++) { 595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(DebugInfo_syms_getidx)( newdi, i, &sym_addr, &sym_toc, 596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NULL, &sym_name_pri, &sym_names_sec, 597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &isText, NULL ); 598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* twoslots[2]; 599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec, 600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &twoslots[0]); 601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names; 602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (names = names_init; *names; names++) { 603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ok = isText 604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && VG_(maybe_Z_demangle)( 605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *names, demangled_sopatt, N_DEMANGLED, 606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov demangled_fnpatt, N_DEMANGLED, &isWrap, NULL, NULL ); 607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!ok) 608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* not a redirect. Ignore. */ 609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sym_toc != 0) 611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* has a valid toc pointer. Ignore. */ 612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (spec = specList; spec; spec = spec->next) 615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (0 == VG_(strcmp)(spec->from_sopatt, demangled_sopatt) 616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && 0 == VG_(strcmp)(spec->from_fnpatt, demangled_fnpatt)) 617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (spec) 619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* a redirect to some other copy of that symbol, which 620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov does have a TOC value, already exists */ 621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Complain */ 624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(message)(Vg_DebugMsg, 625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "WARNING: no TOC ptr for redir/wrap to %s %s\n", 626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov demangled_sopatt, demangled_fnpatt); 627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free_symname_array(names_init, &twoslots[0]); 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok. Now specList holds the list of specs from the DebugInfo. 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Build a new TopSpec, but don't add it to topSpecs yet. */ 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts = dinfo_zalloc("redir.rnnD.4", sizeof(TopSpec)); 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newts); 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->next = NULL; /* not significant */ 637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov newts->seginfo = newdi; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->specs = specList; 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->mark = False; /* not significant */ 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We now need to augment the active set with the following partial 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cross product: 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) actives formed by matching the new specs in specList against 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all symbols currently listed in topSpecs 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (2) actives formed by matching the new symbols in newdi against 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all specs currently listed in topSpecs 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (3) actives formed by matching the new symbols in newdi against 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the new specs in specList 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is necessary in order to maintain the invariant that 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Actives contains all bindings generated by matching ALL specs in 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs against ALL symbols in topSpecs (that is, a cross 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown product of ALL known specs against ALL known symbols). 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Case (1) */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) { 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ts->seginfo) 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_and_add_actives( specList, newts, 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts->seginfo, ts ); 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Case (2) */ 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) { 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_and_add_actives( ts->specs, ts, 668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov newdi, newts ); 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Case (3) */ 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_and_add_actives( specList, newts, 673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov newdi, newts ); 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finally, add the new TopSpec. */ 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->next = topSpecs; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs = newts; 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_redir_state("after VG_(redir_notify_new_DebugInfo)"); 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Really finally (quite unrelated to all the above) check the 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown names in the module against any --require-text-symbol= 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specifications we might have. */ 685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov handle_require_text_symbols(newdi); 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef N_DEMANGLED 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a new target for an indirect function. Adds a new redirection 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the indirection function with address old_from that redirects 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the ordinary function with address new_from to the target address 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the original redirection. */ 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from ) 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active *old, new; 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old = VG_(OSetGen_Lookup)(activeSet, &old_from); 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old->isIFunc); 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new = *old; 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new.from_addr = new_from; 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new.isIFunc = False; 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown maybe_add_active (new); 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) { 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "Adding redirect for indirect function " 711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "0x%llx from 0x%llx -> 0x%llx\n", 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)old_from, (ULong)new_from, (ULong)new.to_addr ); 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do one element of the basic cross product: add to the active set, 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all matches resulting from comparing all the given specs against 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all the symbols in the given seginfo. If a conflicting binding 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would thereby arise, don't add it, but do complain. */ 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid generate_and_add_actives ( 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* spec list and the owning TopSpec */ 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specs, 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_spec, 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* seginfo and the owning TopSpec */ 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di, 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_sym 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Spec* sp; 732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool anyMark, isText, isIFunc; 733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Active act; 734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int nsyms, i; 735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr sym_addr; 736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* sym_name_pri; 737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** sym_names_sec; 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First figure out which of the specs match the seginfo's soname. 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also clear the 'done' bits, so that after the main loop below 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tell which of the Specs really did get done. */ 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anyMark = False; 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = specs; sp; sp = sp->next) { 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp->done = False; 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp->mark = VG_(string_match)( sp->from_sopatt, 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_get_soname)(di) ); 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anyMark = anyMark || sp->mark; 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shortcut: if none of the sonames match, there will be no bindings. */ 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!anyMark) 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate outermost over the symbols in the seginfo, in the hope 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of trashing the caches less. */ 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nsyms = VG_(DebugInfo_syms_howmany)( di ); 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nsyms; i++) { 758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(DebugInfo_syms_getidx)( di, i, &sym_addr, NULL, 759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NULL, &sym_name_pri, &sym_names_sec, 760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &isText, &isIFunc ); 761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* twoslots[2]; 762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec, 763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &twoslots[0]); 764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names; 765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (names = names_init; *names; names++) { 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* ignore data symbols */ 768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!isText) 769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (sp = specs; sp; sp = sp->next) { 772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!sp->mark) 773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; /* soname doesn't match */ 774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(string_match)( sp->from_fnpatt, *names )) { 775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* got a new binding. Add to collection. */ 776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.from_addr = sym_addr; 777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.to_addr = sp->to_addr; 778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.parent_spec = parent_spec; 779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.parent_sym = parent_sym; 780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.becTag = sp->becTag; 781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.becPrio = sp->becPrio; 782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.isWrap = sp->isWrap; 783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.isIFunc = isIFunc; 784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sp->done = True; 785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov maybe_add_active( act ); 786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } /* for (sp = specs; sp; sp = sp->next) */ 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } /* iterating over names[] */ 790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free_symname_array(names_init, &twoslots[0]); 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* for (i = 0; i < nsyms; i++) */ 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now, finally, look for Specs which were marked to be done, but 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown didn't get matched. If any such are mandatory we must abort the 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown system at this point. */ 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = specs; sp; sp = sp->next) { 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sp->mark) 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp->mark && (!sp->done) && sp->mandatory) 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp) { 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar** strp; 804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* v = "valgrind: "; 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sp->mark); 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sp->done); 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sp->mandatory); 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sFatal error at startup: a function redirection\n", v); 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%swhich is mandatory for this platform-tool combination\n", v); 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%scannot be set up. Details of the redirection are:\n", v); 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s\n", v); 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sA must-be-redirected function\n", v); 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%swhose name matches the pattern: %s\n", v, sp->from_fnpatt); 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sin an object with soname matching: %s\n", v, sp->from_sopatt); 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%swas not found whilst processing\n", v); 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%ssymbols from the object with soname: %s\n", 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v, VG_(DebugInfo_get_soname)(di)); 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s\n", v); 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (strp = sp->mandatory; *strp; strp++) 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s%s\n", v, *strp); 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s\n", v); 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sCannot continue -- exiting now. Sorry.\n", v); 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add an act (passed by value; is copied here) and deal with 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown conflicting bindings. */ 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void maybe_add_active ( Active act ) 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* what = NULL; 850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Active* old = NULL; 851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool add_act = False; 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Complain and ignore manifestly bogus 'from' addresses. 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Kludge: because this can get called befor the trampoline area (a 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bunch of magic 'to' addresses) has its ownership changed from V 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to C, we can't check the 'to' address similarly. Sigh. 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64-linux hack: the vsysinfo pages appear to have no 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown permissions 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so skip the check for them. */ 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_plausible_guest_addr(act.from_addr) 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_amd64_linux) 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act.from_addr != 0xFFFFFFFFFF600000ULL 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act.from_addr != 0xFFFFFFFFFF600400ULL 867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && act.from_addr != 0xFFFFFFFFFF600800ULL 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) { 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what = "redirection from-address is in non-executable area"; 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr ); 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old) { 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dodgy. Conflicting binding. */ 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old->from_addr == act.from_addr); 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old->to_addr != act.to_addr) { 879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* We've got a conflicting binding -- that is, from_addr is 880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov specified to redirect to two different destinations, 881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov old->to_addr and act.to_addr. If we can prove that they 882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov are behaviourally equivalent then that's no problem. So 883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov we can look at the behavioural eclass tags for both 884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov functions to see if that's so. If they are equal, and 885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov nonzero, then that's fine. But if not, we can't show they 886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov are equivalent, so we have to complain, and ignore the new 887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov binding. */ 888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(old->becTag >= 0 && old->becTag <= 9999); 889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(old->becPrio >= 0 && old->becPrio <= 9); 890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(act.becTag >= 0 && act.becTag <= 9999); 891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(act.becPrio >= 0 && act.becPrio <= 9); 892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (old->becTag == 0) 893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(old->becPrio == 0); 894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (act.becTag == 0) 895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(act.becPrio == 0); 896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (old->becTag == 0 || act.becTag == 0 || old->becTag != act.becTag) { 898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* We can't show that they are equivalent. Complain and 899b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ignore. */ 900b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov what = "new redirection conflicts with existing -- ignoring it"; 901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto bad; 902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* They have the same eclass tag. Use the priorities to 904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov resolve the ambiguity. */ 905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (act.becPrio <= old->becPrio) { 906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* The new one doesn't have a higher priority, so just 907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ignore it. */ 908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_verbosity) > 2) { 909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(message)(Vg_UserMsg, "Ignoring %s redirection:\n", 910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.becPrio < old->becPrio ? "lower priority" 911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov : "duplicate"); 912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_active( " old: ", old); 913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_active( " new: ", &act); 914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* The tricky case. The new one has a higher priority, so 917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov we need to get the old one out of the OSet and install 918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov this one in its place. */ 919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_verbosity) > 1) { 920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(message)(Vg_UserMsg, 921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "Preferring higher priority redirection:\n"); 922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_active( " old: ", old); 923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_active( " new: ", &act); 924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov add_act = True; 926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov void* oldNd = VG_(OSetGen_Remove)( activeSet, &act.from_addr ); 927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(oldNd == old); 928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(OSetGen_FreeNode)( activeSet, old ); 929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov old = NULL; 930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This appears to be a duplicate of an existing binding. 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Safe(ish) -- ignore. */ 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* XXXXXXXXXXX COMPLAIN if new and old parents differ */ 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* There's no previous binding for this from_addr, so we must 939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov add 'act' to the active set. */ 940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov add_act = True; 941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* So, finally, actually add it. */ 944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (add_act) { 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active)); 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *a = act; 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_Insert)(activeSet, a); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now that a new from->to redirection is in force, we need to 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get rid of any translations intersecting 'from' in order that 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they get redirected to 'to'. So discard them. Just for 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown paranoia (but, I believe, unnecessarily), discard 'to' as 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown well. */ 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act.from_addr, 1, 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_new_DebugInfo(from_addr)"); 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act.to_addr, 1, 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_new_DebugInfo(to_addr)"); 958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_verbosity) > 2) { 959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(message)(Vg_UserMsg, "Adding active redirection:\n"); 960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_active( " new: ", &act); 961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad: 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(what); 967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(!add_act); 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) { 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "WARNING: %s\n", what); 970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (old) { 971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_active( " old: ", old); 972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_active( " new: ", &act); 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notify m_redir of the deletion of a DebugInfo. This is relatively 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simple -- just get rid of all actives derived from it, and free up 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the associated list elements. */ 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_notify_delete_DebugInfo)( DebugInfo* delsi ) 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* ts; 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* tsPrev; 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp; 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp_next; 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* tmpSet; 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* act; 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool delMe; 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(delsi); 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Search for it, and make tsPrev point to the previous entry, if 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any. */ 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsPrev = NULL; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts = topSpecs; 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ts == NULL) break; 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ts->seginfo == delsi) break; 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsPrev = ts; 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts = ts->next; 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ts); /* else we don't have the deleted DebugInfo */ 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ts->seginfo == delsi); 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Traverse the actives, copying the addresses of those we intend 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to delete into tmpSet. */ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpSet = VG_(OSetWord_Create)(dinfo_zalloc, "redir.rndD.1", dinfo_free); 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts->mark = True; 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)( activeSet ); 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (act = VG_(OSetGen_Next)(activeSet)) ) { 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delMe = act->parent_spec != NULL 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_sym != NULL 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_spec->seginfo != NULL 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_sym->seginfo != NULL 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (act->parent_spec->mark || act->parent_sym->mark); 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* While we're at it, a bit of paranoia: delete any actives 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which don't have both feet in valid client executable areas. 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown But don't delete hardwired-at-startup ones; these are denoted 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by having parent_spec or parent_sym being NULL. */ 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (!delMe) 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_spec != NULL 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_sym != NULL ) { 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_plausible_guest_addr(act->from_addr)) 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delMe = True; 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_plausible_guest_addr(act->to_addr)) 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delMe = True; 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (delMe) { 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetWord_Insert)( tmpSet, act->from_addr ); 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* While we have our hands on both the 'from' and 'to' 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of this Active, do paranoid stuff with tt/tc. */ 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act->from_addr, 1, 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_del_DebugInfo(from_addr)"); 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act->to_addr, 1, 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_del_DebugInfo(to_addr)"); 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now traverse tmpSet, deleting corresponding elements in activeSet. */ 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetWord_ResetIter)( tmpSet ); 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( VG_(OSetWord_Next)(tmpSet, &addr) ) { 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act = VG_(OSetGen_Remove)( activeSet, &addr ); 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(act); 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_FreeNode)( activeSet, act ); 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetWord_Destroy)( tmpSet ); 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The Actives set is now cleaned up. Free up this TopSpec and 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown everything hanging off it. */ 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = ts->specs; sp; sp = sp_next) { 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp->from_sopatt) dinfo_free(sp->from_sopatt); 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp->from_fnpatt) dinfo_free(sp->from_fnpatt); 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp_next = sp->next; 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_free(sp); 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tsPrev == NULL) { 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first in list */ 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs = ts->next; 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsPrev->next = ts->next; 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_free(ts); 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_redir_state("after VG_(redir_notify_delete_DebugInfo)"); 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- QUERIES (really the whole point of this module) ---*/ 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the crucial redirection function. It answers the question: 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should this code address be redirected somewhere else? It's used 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown just before translating a basic block. */ 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap ) 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* r = VG_(OSetGen_Lookup)(activeSet, &orig); 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (r == NULL) 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return orig; 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(r->to_addr != 0); 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isWrap) 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *isWrap = r->isWrap || r->isIFunc; 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (r->isIFunc) { 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(iFuncWrapper); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iFuncWrapper; 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r->to_addr; 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- INITIALISATION ---*/ 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a never-delete-me Active. */ 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) /* only used on amd64 */ 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_hardwired_active ( Addr from, Addr to ) 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active act; 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.from_addr = from; 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.to_addr = to; 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.parent_spec = NULL; 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.parent_sym = NULL; 1117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.becTag = 0; /* "not equivalent to any other fn" */ 1118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act.becPrio = 0; /* mandatory when becTag == 0 */ 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.isWrap = False; 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.isIFunc = False; 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown maybe_add_active( act ); 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a never-delete-me Spec. This is a bit of a kludge. On the 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assumption that this is called only at startup, only handle the 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case where topSpecs is completely empty, or if it isn't, it has 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown just one entry and that is the one with NULL seginfo -- that is the 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entry that holds these initial specs. */ 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) /* not used on all platforms */ 1132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void add_hardwired_spec (const HChar* sopatt, const HChar* fnpatt, 1133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Addr to_addr, 1134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar** mandatory ) 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec)); 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(spec); 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (topSpecs == NULL) { 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs = dinfo_zalloc("redir.ahs.2", sizeof(TopSpec)); 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs); 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* symtab_zalloc sets all fields to zero */ 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs != NULL); 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs->next == NULL); 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs->seginfo == NULL); 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXED PARTS */ 1149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov spec->from_sopatt = (HChar *)sopatt; 1150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov spec->from_fnpatt = (HChar *)fnpatt; 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->to_addr = to_addr; 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->isWrap = False; 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->mandatory = mandatory; 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VARIABLE PARTS */ 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->mark = False; /* not significant */ 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->done = False; /* not significant */ 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->next = topSpecs->specs; 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs->specs = spec; 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) /* not used on all platforms */ 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const HChar* complain_about_stripped_glibc_ldso[] 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown= { "Possible fixes: (1, short term): install glibc's debuginfo", 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "package on this machine. (2, longer term): ask the packagers", 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "for your Linux distribution to please in future ship a non-", 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "stripped ld.so (or whatever the dynamic linker .so is called)", 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "that exports the above-named function using the standard", 1170f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root "calling conventions for this platform. The package you need", 1171f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root "to install for fix (1) is called", 1172f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root "", 1173f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root " On Debian, Ubuntu: libc6-dbg", 1174f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root " On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo", 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown }; 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the redir system, and create the initial Spec list and 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for amd64-linux a couple of permanent active mappings. The initial 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specs are not converted into Actives yet, on the (checked) 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assumption that no DebugInfos have so far been created, and so when 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they are created, that will happen. */ 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_initialise) ( void ) 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Assert that there are no DebugInfos so far 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(next_DebugInfo)(NULL) == NULL ); 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Initialise active mapping. 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr), 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, // Use fast comparison 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_zalloc, 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir.ri.1", 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_free); 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The rest of this function just adds initial Specs. 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use this intercept right from the 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */ 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const HChar** mandatory; 1204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(GLIBC_2_2) || defined(GLIBC_2_3) || defined(GLIBC_2_4) \ 1205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(GLIBC_2_5) || defined(GLIBC_2_6) || defined(GLIBC_2_7) \ 1206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(GLIBC_2_8) || defined(GLIBC_2_9) \ 1207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(GLIBC_2_10) || defined(GLIBC_2_11) 1208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mandatory = NULL; 1209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 1210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* for glibc-2.12 and later, this is mandatory - can't sanely 1211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue without it */ 1212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mandatory = complain_about_stripped_glibc_ldso; 1213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux.so.2", "index", 1216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (Addr)&VG_(x86_linux_REDIR_FOR_index), mandatory); 1217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov add_hardwired_spec( 1218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "ld-linux.so.2", "strlen", 1219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (Addr)&VG_(x86_linux_REDIR_FOR_strlen), mandatory); 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Redirect vsyscalls to local versions */ 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_active( 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xFFFFFFFFFF600000ULL, 1226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday) 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng add_hardwired_active( 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xFFFFFFFFFF600400ULL, 1230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (Addr)&VG_(amd64_linux_REDIR_FOR_vtime) 1231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ); 1232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng add_hardwired_active( 1233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0xFFFFFFFFFF600800ULL, 1234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (Addr)&VG_(amd64_linux_REDIR_FOR_vgetcpu) 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux-x86-64.so.2", "strlen", 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_linux_REDIR_FOR_strlen), 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(GLIBC_2_2) || defined(GLIBC_2_3) || defined(GLIBC_2_4) \ 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || defined(GLIBC_2_5) || defined(GLIBC_2_6) || defined(GLIBC_2_7) \ 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || defined(GLIBC_2_8) || defined(GLIBC_2_9) 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* for glibc-2.10 and later, this is mandatory - can't sanely 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue without it */ 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc32_linux) 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is mandatory - can't sanely continue without it */ 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld.so.1", "strlen", 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen), 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld.so.1", "strcmp", 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp), 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL /* not mandatory - so why bother at all? */ 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */ 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld.so.1", "index", 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(ppc32_linux_REDIR_FOR_strchr), 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL /* not mandatory - so why bother at all? */ 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */ 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_linux) 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is mandatory - can't sanely continue without it */ 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld64.so.1", "strlen", 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ), 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld64.so.1", "index", 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strchr) ), 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL /* not mandatory - so why bother at all? */ 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* glibc-2.5 (FC6, ppc64) seems fine without it */ 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_arm_linux) 1302eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov /* If we're using memcheck, use these intercepts right from the 1303eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov start, otherwise ld.so makes a lot of noise. In most ARM-linux 1304eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov distros, ld.so's soname is ld-linux.so.3, but Ubuntu 14.04 on 1305eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov Odroid uses ld-linux-armhf.so.3 for some reason. */ 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1307eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov /* strlen */ 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux.so.3", "strlen", 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(arm_linux_REDIR_FOR_strlen), 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1313eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov add_hardwired_spec( 1314eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "ld-linux-armhf.so.3", "strlen", 1315eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (Addr)&VG_(arm_linux_REDIR_FOR_strlen), 1316eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov complain_about_stripped_glibc_ldso 1317eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ); 1318eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov /* memcpy */ 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux.so.3", "memcpy", 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(arm_linux_REDIR_FOR_memcpy), 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1324eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov add_hardwired_spec( 1325eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "ld-linux-armhf.so.3", "memcpy", 1326eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (Addr)&VG_(arm_linux_REDIR_FOR_memcpy), 1327eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov complain_about_stripped_glibc_ldso 1328eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ); 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# elif defined(VGP_arm64_linux) 1332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* If we're using memcheck, use these intercepts right from 1333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the start, otherwise ld.so makes a lot of noise. */ 1334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 13352ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov add_hardwired_spec( 13362ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov "ld-linux-aarch64.so.1", "strlen", 13372ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov (Addr)&VG_(arm64_linux_REDIR_FOR_strlen), 13382ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov complain_about_stripped_glibc_ldso 13392ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov ); 13402ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov add_hardwired_spec( 13412ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov "ld-linux-aarch64.so.1", "index", 13422ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov (Addr)&VG_(arm64_linux_REDIR_FOR_index), 13432ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov NULL 13442ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov ); 13452ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov add_hardwired_spec( 13462ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov "ld-linux-aarch64.so.1", "strcmp", 13472ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov (Addr)&VG_(arm64_linux_REDIR_FOR_strcmp), 13482ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov NULL 13492ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov ); 13502ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov //add_hardwired_spec( 13512ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov // "ld-linux.so.3", "memcpy", 13522ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov // (Addr)&VG_(arm_linux_REDIR_FOR_memcpy), 13532ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov // complain_about_stripped_glibc_ldso 13542ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov //); 1355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise dyld makes a lot of noise. */ 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcmp", 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strcmp), NULL); 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlen", 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strlen), NULL); 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcat", 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strcat), NULL); 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcpy", 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strcpy), NULL); 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlcat", 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strlcat), NULL); 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise dyld makes a lot of noise. */ 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcmp", 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strcmp), NULL); 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlen", 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strlen), NULL); 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcat", 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strcat), NULL); 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcpy", 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strcpy), NULL); 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlcat", 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strlcat), NULL); 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: #warning fixme rdar://6166275 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "arc4random", 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_arc4random), NULL); 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGP_s390x_linux) 1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* nothing so far */ 1394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_mips32_linux) 1396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* this is mandatory - can't sanely continue without it */ 1399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng add_hardwired_spec( 1400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "ld.so.3", "strlen", 1401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (Addr)&VG_(mips32_linux_REDIR_FOR_strlen), 1402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng complain_about_stripped_glibc_ldso 1403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ); 1404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# elif defined(VGP_mips64_linux) 1407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* this is mandatory - can't sanely continue without it */ 1410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_hardwired_spec( 1411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "ld.so.3", "strlen", 1412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (Addr)&VG_(mips64_linux_REDIR_FOR_strlen), 1413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov complain_about_stripped_glibc_ldso 1414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ); 1415436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1416436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_redir_state("after VG_(redir_initialise)"); 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- MISC HELPERS ---*/ 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void* dinfo_zalloc(const HChar* ec, SizeT n) { 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* p; 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n > 0); 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = VG_(arena_malloc)(VG_AR_DINFO, ec, n); 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(p); 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(p, 0, n); 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return p; 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void dinfo_free(void* p) { 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(p); 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_free)(VG_AR_DINFO, p); 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* dinfo_strdup(const HChar* ec, const HChar* str) 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_strdup)(VG_AR_DINFO, ec, str); 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Really this should be merged with translations_allowable_from_seg 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in m_translate. */ 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_plausible_guest_addr(Addr a) 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg = VG_(am_find_nsegment)(a); 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return seg != NULL 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (seg->kind == SkAnonC || seg->kind == SkFileC) 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (seg->hasX || seg->hasR); /* crude x86-specific hack */ 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NOTIFY-ON-LOAD FUNCTIONS ---*/ 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid handle_maybe_load_notifier( const HChar* soname, 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* symbol, Addr addr ) 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* x86-linux only: if we see _dl_sysinfo_int80, note its address. 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See comment on declaration of VG_(client__dl_sysinfo_int80) for 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the reason. As far as I can tell, the relevant symbol is always 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in object with soname "ld-linux.so.2". */ 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (symbol && symbol[0] == '_' 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == VG_(strcmp)(symbol, "_dl_sysinfo_int80") 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == VG_(strcmp)(soname, "ld-linux.so.2")) { 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(client__dl_sysinfo_int80) == 0) 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client__dl_sysinfo_int80) = addr; 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Normal load-notifier handling after here. First, ignore all 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols lacking the right prefix. */ 1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(symbol); // assert rather than segfault if it is NULL 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 != VG_(strncmp)(symbol, VG_NOTIFY_ON_LOAD_PREFIX, 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_NOTIFY_ON_LOAD_PREFIX_LEN)) 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't have the right prefix */ 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0) 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client___libc_freeres_wrapper) = addr; 1491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0) 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iFuncWrapper = addr; 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "unrecognised load notification function: %s", symbol); 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- REQUIRE-TEXT-SYMBOL HANDLING ---*/ 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In short: check that the currently-being-loaded object has text 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols that satisfy any --require-text-symbol= specifications that 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown apply to it, and abort the run with an error message if not. 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_require_text_symbols ( DebugInfo* di ) 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First thing to do is figure out which, if any, 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --require-text-symbol specification strings apply to this 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object. Most likely none do, since it is not expected to 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frequently be used. Work through the list of specs and 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accumulate in fnpatts[] the fn patterns that pertain to this 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object. */ 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnpatts[VG_CLO_MAX_REQ_TSYMS]; 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fnpatts_used = 0; 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, j; 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar* di_soname = VG_(DebugInfo_get_soname)(di); 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di_soname); // must be present 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&fnpatts, 0, sizeof(fnpatts)); 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(clo_n_req_tsyms) >= 0); 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(clo_n_req_tsyms) <= VG_CLO_MAX_REQ_TSYMS); 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(clo_n_req_tsyms); i++) { 1526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* clo_spec = VG_(clo_req_tsyms)[i]; 1527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(clo_spec && VG_(strlen)(clo_spec) >= 4); 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // clone the spec, so we can stick a zero at the end of the sopatt 1529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar *spec = VG_(strdup)("m_redir.hrts.1", clo_spec); 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar sep = spec[0]; 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* sopatt = &spec[1]; 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnpatt = VG_(strchr)(sopatt, sep); 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the initial check at clo processing in time in m_main 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // should ensure this. 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(fnpatt && *fnpatt == sep); 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *fnpatt = 0; 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnpatt++; 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(string_match)(sopatt, di_soname)) 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnpatts[fnpatts_used++] 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(strdup)("m_redir.hrts.2", fnpatt); 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(spec); 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fnpatts_used == 0) 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* no applicable spec strings */ 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So finally, fnpatts[0 .. fnpatts_used - 1] contains the set of 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (patterns for) text symbol names that must be found in this 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object, in order to continue. That is, we must find at least 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown one text symbol name that matches each pattern, else we must 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown abort the run. */ 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("for %s\n", di_soname); 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fnpatts_used; i++) 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)(" fnpatt: %s\n", fnpatts[i]); 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For each spec, look through the syms to find one that matches. 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This isn't terribly efficient but it happens rarely, so no big 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deal. */ 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fnpatts_used; i++) { 1561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool found = False; 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnpatt = fnpatts[i]; 1563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int nsyms = VG_(DebugInfo_syms_howmany)(di); 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < nsyms; j++) { 1565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool isText = False; 1566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* sym_name_pri = NULL; 1567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** sym_names_sec = NULL; 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_syms_getidx)( di, j, NULL, NULL, 1569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NULL, &sym_name_pri, &sym_names_sec, 1570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &isText, NULL ); 1571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* twoslots[2]; 1572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec, 1573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &twoslots[0]); 1574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar** names; 1575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (names = names_init; *names; names++) { 1576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* ignore data symbols */ 1577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (0) VG_(printf)("QQQ %s\n", *names); 1578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(sym_name_pri); 1579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!isText) 1580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 1581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(string_match)(fnpatt, *names)) { 1582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov found = True; 1583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 1584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 15859bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root } 1586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free_symname_array(names_init, &twoslots[0]); 1587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (found) 1588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found) { 1592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* v = "valgrind: "; 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sFatal error at when loading library with soname\n", v); 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s %s\n", v, di_soname); 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sCannot find any text symbol with a name " 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "that matches the pattern\n", v); 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%s %s\n", v, fnpatt); 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%sas required by a --require-text-symbol= " 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "specification.\n", v); 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sCannot continue -- exiting now.\n", v); 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All required specs were found. Just free memory and return. */ 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fnpatts_used; i++) 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(fnpatts[i]); 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- SANITY/DEBUG ---*/ 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_spec ( const HChar* left, Spec* spec ) 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 1625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "%s%25s %30s %s-> (%04d.%d) 0x%08llx\n", 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown left, 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->from_sopatt, spec->from_fnpatt, 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->isWrap ? "W" : "R", 1629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov spec->becTag, spec->becPrio, 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)spec->to_addr ); 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_active ( const HChar* left, Active* act ) 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar name1[64] = ""; 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar name2[64] = ""; 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name1[0] = name2[0] = 0; 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(get_fnname_w_offset)(act->from_addr, name1, 64); 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) VG_(strcpy)(name1, "???"); 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(get_fnname_w_offset)(act->to_addr, name2, 64); 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) VG_(strcpy)(name2, "???"); 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> (%04d.%d) 0x%08llx %s\n", 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown left, 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)act->from_addr, name1, 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act->isWrap ? "W" : "R", 1648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov act->becTag, act->becPrio, 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)act->to_addr, name2 ); 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_redir_state ( const HChar* who ) 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* ts; 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp; 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* act; 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "<<\n"); 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " ------ REDIR STATE %s ------\n", who); 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) { 1660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (ts->seginfo) 1661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)(Vg_DebugMsg, 1662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " TOPSPECS of soname %s filename %s\n", 1663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(DebugInfo_get_soname)(ts->seginfo), 1664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(DebugInfo_get_filename)(ts->seginfo)); 1665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else 1666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)(Vg_DebugMsg, 1667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " TOPSPECS of soname (hardwired)\n"); 1668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = ts->specs; sp; sp = sp->next) 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_spec(" ", sp); 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------\n"); 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)( activeSet ); 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (act = VG_(OSetGen_Next)(activeSet)) ) { 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_active(" ", act); 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, ">>\n"); 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1684