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 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copyright (C) 2000-2010 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copyright (C) 2003-2010 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" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_seqmatch.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_oset.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" // VG_(needs).malloc_replacement 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" // VG_(fnptr_to_fnentry) 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" // VG_(am_find_nsegment) 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" // VG_(client___libc_freeres_wrapper) 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_demangle.h" // VG_(maybe_Z_demangle) 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h" /* GLIBC_2_* */ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This module is a critical part of the redirection/intercept system. 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It keeps track of the current intercept state, cleans up the 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation caches when that state changes, and finally, answers 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queries about the whether an address is currently redirected or 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not. It doesn't do any of the control-flow trickery needed to put 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the redirections into practice. That is the job of m_translate, 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which calls here to find out which translations need to be 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirected. 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The interface is simple. VG_(redir_initialise) initialises and 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loads some hardwired redirects which never disappear; this is 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform-specific. 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The module is notified of redirection state changes by m_debuginfo. 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That calls VG_(redir_notify_new_DebugInfo) when a new DebugInfo 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (shared object symbol table, basically) appears. Appearance of new 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols can cause new (active) redirections to appear for two 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reasons: the symbols in the new table may match existing 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redirection specifications (see comments below), and because the 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols in the new table may themselves supply new redirect 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specifications which match existing symbols (or ones in the new 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown table). 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Redirect specifications are really symbols with "funny" prefixes 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_vgrZU_ and _vgrZZ_). These names tell m_redir that the 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown associated code should replace the standard entry point for some 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set of functions. The set of functions is specified by a (soname 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pattern, function name pattern) pair which is encoded in the symbol 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name following the prefix. The names use a Z-encoding scheme so 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that they may contain punctuation characters and wildcards (*). 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The encoding scheme is described in pub_tool_redir.h and is decoded 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by VG_(maybe_Z_demangle). 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a shared object is unloaded, this module learns of it via a 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call to VG_(redir_notify_delete_DebugInfo). It then removes from 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown its tables all active redirections in any way associated with that 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object, and tidies up the translation caches accordingly. 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That takes care of tracking the redirection state. When a 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation is actually to be made, m_translate calls to 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_do_lookup) in this module to find out if the 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translation's address should be redirected. 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Semantics ---*/ 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The redirector holds two pieces of state: 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specs - a set of (soname pattern, fnname pattern) -> redir addr 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active - a set of orig addr -> (bool, redir addr) 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active is the currently active set of bindings that the translator 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown consults. Specs is the current set of specifications as harvested 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from reading symbol tables of the currently loaded objects. 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active is a pure function of Specs and the current symbol table 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state (maintained by m_debuginfo). Call the latter SyminfoState. 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Therefore whenever either Specs or SyminfoState changes, Active 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown must be recomputed. [Inefficient if done naively, but this is a 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec]. 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active is computed as follows: 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active = empty 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for spec in Specs { 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sopatt = spec.soname pattern 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnpatt = spec.fnname pattern 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redir = spec.redir addr 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for so matching sopatt in SyminfoState { 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for fn matching fnpatt in fnnames_of(so) { 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &fn -> redir is added to Active 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [as an implementation detail, when a binding (orig -> redir) is 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deleted from Active as a result of recomputing it, then all 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown translations intersecting redir must be deleted. However, this is 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not part of the spec]. 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [Active also depends on where the aspacemgr has decided to put all 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the pieces of code -- that affects the "orig addr" and "redir addr" 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown values.] 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --------------------- 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown That completes the spec, apart from one difficult issue: duplicates. 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Clearly we must impose the requirement that domain(Active) contains 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown no duplicates. The difficulty is how to constrain Specs enough to 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown avoid getting into that situation. It's easy to write specs which 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown could cause conflicting bindings in Active, eg: 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_mutex_lock) -> a1 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_*) -> a2 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for a1 != a2. Or even hairier: 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_mutex_*) -> a1 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (libpthread.so, pthread_*_lock) -> a2 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I can't think of any sane way of detecting when an addition to 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specs would generate conflicts. However, considering we don't 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown actually want to have a system that allows this, I propose this: 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all changes to Specs are acceptable. But, when recomputing Active 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown following the change, if the same orig is bound to more than one 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown redir, then the first binding for orig is retained, and all the 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rest ignored. 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown =========================================================== 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown =========================================================== 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Incremental implementation: 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a new DebugInfo appears: 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - it may be the source of new specs 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - it may be the source of new matches for existing specs 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Therefore: 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (new Specs x existing DebugInfos): scan all symbols in the new 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo to find new specs. Each of these needs to be compared 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown against all symbols in all the existing DebugInfos to generate 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new actives. 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (existing Specs x new DebugInfo): scan all symbols in the 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo, trying to match them to any existing specs, also 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generating new actives. 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - (new Specs x new DebugInfo): scan all symbols in the new 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo, trying to match them against the new specs, to 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate new actives. 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Finally, add new new specs to the current set of specs. 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When adding a new active (s,d) to the Actives: 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookup s in Actives 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if already bound to d, ignore 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if already bound to something other than d, complain loudly and ignore 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else add (s,d) to Actives 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and discard (s,1) and (d,1) (maybe overly conservative) 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a DebugInfo disappears: 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - delete all specs acquired from the seginfo 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - delete all actives derived from the just-deleted specs 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - if each active (s,d) deleted, discard (s,1) and (d,1) 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- REDIRECTION SPECIFICATIONS ---*/ 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A specification of a redirection we want to do. Note that because 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both the "from" soname and function name may contain wildcards, the 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec can match an arbitrary number of times. 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16 Nov 2007: Comments re .mandatory field: The initial motivation 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for this is making Memcheck work sanely on glibc-2.6.X ppc32-linux. 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We really need to intercept 'strlen' in ld.so right from startup. 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If ld.so does not have a visible 'strlen' symbol, Memcheck 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generates an impossible number of errors resulting from highly 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tuned strlen implementation in ld.so, and is completely unusable 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -- the resulting undefinedness eventually seeps everywhere. */ 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _Spec { 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _Spec* next; /* linked list */ 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXED PARTS -- set when created and not changed */ 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* from_sopatt; /* from soname pattern */ 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* from_fnpatt; /* from fnname pattern */ 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr to_addr; /* where redirecting to */ 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isWrap; /* wrap or replacement? */ 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar** mandatory; /* non-NULL ==> abort V and print the 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strings if from_sopatt is loaded but 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown from_fnpatt cannot be found */ 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VARIABLE PARTS -- used transiently whilst processing redirections */ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool mark; /* set if spec requires further processing */ 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool done; /* set if spec was successfully matched */ 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec; 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Top-level data structure. It contains a pointer to a DebugInfo and 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown also a list of the specs harvested from that DebugInfo. Note that 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seginfo is allowed to be NULL, meaning that the specs are 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pre-loaded ones at startup and are not associated with any 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown particular seginfo. */ 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _TopSpec { 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _TopSpec* next; /* linked list */ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* seginfo; /* symbols etc */ 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specs; /* specs pulled out of seginfo */ 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool mark; /* transient temporary used during deletion */ 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the top level list of redirections. m_debuginfo maintains 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a list of DebugInfos, and the idea here is to maintain a list with 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same number of elements (in fact, with one more element, so as 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to record abovementioned preloaded specifications.) */ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic TopSpec* topSpecs = NULL; 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- CURRENTLY ACTIVE REDIRECTIONS ---*/ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Represents a currently active binding. If either parent_spec or 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parent_sym is NULL, then this binding was hardwired at startup and 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should not be deleted. Same is true if either parent's seginfo 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown field is NULL. */ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr from_addr; /* old addr -- MUST BE THE FIRST WORD! */ 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr to_addr; /* where redirecting to */ 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_spec; /* the TopSpec which supplied the Spec */ 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_sym; /* the TopSpec which supplied the symbol */ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isWrap; /* wrap or replacement? */ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isIFunc; /* indirect function? */ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active; 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The active set is a fast lookup table */ 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OSet* activeSet = NULL; 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Wrapper routine for indirect functions */ 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr iFuncWrapper; 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- FWDses ---*/ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void maybe_add_active ( Active /*by value; callee copies*/ ); 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* dinfo_zalloc(HChar* ec, SizeT); 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void dinfo_free(void*); 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* dinfo_strdup(HChar* ec, HChar*); 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_plausible_guest_addr(Addr); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_aix5_glink_idiom(Addr); 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void show_redir_state ( HChar* who ); 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void show_active ( HChar* left, Active* act ); 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_maybe_load_notifier( const UChar* soname, 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* symbol, Addr addr ); 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_require_text_symbols ( DebugInfo* ); 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NOTIFICATIONS ---*/ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid generate_and_add_actives ( 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* spec list and the owning TopSpec */ 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specs, 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_spec, 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* debuginfo and the owning TopSpec */ 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di, 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_sym 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notify m_redir of the arrival of a new DebugInfo. This is fairly 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complex, but the net effect is to (1) add a new entry to the 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topspecs list, and (2) figure out what new binding are now active, 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and, as a result, add them to the actives mapping. */ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_DEMANGLED 256 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi ) 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok, isWrap; 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, nsyms; 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specList; 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* spec; 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* ts; 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* newts; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* sym_name; 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sym_addr, sym_toc; 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar demangled_sopatt[N_DEMANGLED]; 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar demangled_fnpatt[N_DEMANGLED]; 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool check_ppcTOCs = False; 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isText; 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const UChar* newsi_soname; 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_PLAT_USES_PPCTOC) 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_ppcTOCs = True; 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newsi); 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newsi_soname = VG_(DebugInfo_get_soname)(newsi); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newsi_soname != NULL); 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* stay sane: we don't already have this. */ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ts->seginfo != newsi); 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* scan this DebugInfo's symbol table, pulling out and demangling 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any specs found */ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specList = NULL; /* the spec list we're building up */ 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nsyms = VG_(DebugInfo_syms_howmany)( newsi ); 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nsyms; i++) { 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc, 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, &sym_name, &isText, NULL ); 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANGLED, 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown demangled_fnpatt, N_DEMANGLED, &isWrap ); 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ignore data symbols */ 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!isText) 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) { 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It's not a full-scale redirect, but perhaps it is a load-notify 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn? Let the load-notify department see it. */ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_maybe_load_notifier( newsi_soname, sym_name, sym_addr ); 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (check_ppcTOCs && sym_toc == 0) { 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This platform uses toc pointers, but none could be found 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for this symbol, so we can't safely redirect/wrap to it. 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Just skip it; we'll make a second pass over the symbols in 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the following loop, and complain at that point. */ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec = dinfo_zalloc("redir.rnnD.1", sizeof(Spec)); 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(spec); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->from_sopatt = dinfo_strdup("redir.rnnD.2", demangled_sopatt); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->from_fnpatt = dinfo_strdup("redir.rnnD.3", demangled_fnpatt); 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(spec->from_sopatt); 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(spec->from_fnpatt); 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->to_addr = sym_addr; 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->isWrap = isWrap; 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* check we're not adding manifestly stupid destinations */ 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(is_plausible_guest_addr(sym_addr)); 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->next = specList; 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->mark = False; /* not significant */ 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->done = False; /* not significant */ 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specList = spec; 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (check_ppcTOCs) { 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nsyms; i++) { 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc, 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, &sym_name, &isText, NULL ); 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = isText 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && VG_(maybe_Z_demangle)( 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sym_name, demangled_sopatt, N_DEMANGLED, 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown demangled_fnpatt, N_DEMANGLED, &isWrap ); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* not a redirect. Ignore. */ 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sym_toc != 0) 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* has a valid toc pointer. Ignore. */ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (spec = specList; spec; spec = spec->next) 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(spec->from_sopatt, demangled_sopatt) 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == VG_(strcmp)(spec->from_fnpatt, demangled_fnpatt)) 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (spec) 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* a redirect to some other copy of that symbol, which 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does have a TOC value, already exists */ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Complain */ 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "WARNING: no TOC ptr for redir/wrap to %s %s\n", 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown demangled_sopatt, demangled_fnpatt); 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok. Now specList holds the list of specs from the DebugInfo. 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Build a new TopSpec, but don't add it to topSpecs yet. */ 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts = dinfo_zalloc("redir.rnnD.4", sizeof(TopSpec)); 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newts); 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->next = NULL; /* not significant */ 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->seginfo = newsi; 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->specs = specList; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->mark = False; /* not significant */ 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We now need to augment the active set with the following partial 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cross product: 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (1) actives formed by matching the new specs in specList against 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all symbols currently listed in topSpecs 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (2) actives formed by matching the new symbols in newsi against 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all specs currently listed in topSpecs 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (3) actives formed by matching the new symbols in newsi against 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the new specs in specList 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is necessary in order to maintain the invariant that 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Actives contains all bindings generated by matching ALL specs in 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs against ALL symbols in topSpecs (that is, a cross 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown product of ALL known specs against ALL known symbols). 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Case (1) */ 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) { 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ts->seginfo) 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_and_add_actives( specList, newts, 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts->seginfo, ts ); 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Case (2) */ 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) { 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_and_add_actives( ts->specs, ts, 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newsi, newts ); 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Case (3) */ 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generate_and_add_actives( specList, newts, 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newsi, newts ); 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finally, add the new TopSpec. */ 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newts->next = topSpecs; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs = newts; 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_redir_state("after VG_(redir_notify_new_DebugInfo)"); 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Really finally (quite unrelated to all the above) check the 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown names in the module against any --require-text-symbol= 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown specifications we might have. */ 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_require_text_symbols(newsi); 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef N_DEMANGLED 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a new target for an indirect function. Adds a new redirection 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the indirection function with address old_from that redirects 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the ordinary function with address new_from to the target address 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the original redirection. */ 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from ) 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active *old, new; 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old = VG_(OSetGen_Lookup)(activeSet, &old_from); 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old); 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old->isIFunc); 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new = *old; 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new.from_addr = new_from; 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new.isIFunc = False; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown maybe_add_active (new); 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) { 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Adding redirect for indirect function 0x%llx from 0x%llx -> 0x%llx\n", 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)old_from, (ULong)new_from, (ULong)new.to_addr ); 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do one element of the basic cross product: add to the active set, 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all matches resulting from comparing all the given specs against 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all the symbols in the given seginfo. If a conflicting binding 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would thereby arise, don't add it, but do complain. */ 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid generate_and_add_actives ( 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* spec list and the owning TopSpec */ 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* specs, 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_spec, 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* seginfo and the owning TopSpec */ 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DebugInfo* di, 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* parent_sym 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp; 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool anyMark, isText, isIFunc; 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active act; 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nsyms, i; 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr sym_addr; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* sym_name; 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First figure out which of the specs match the seginfo's soname. 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also clear the 'done' bits, so that after the main loop below 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tell which of the Specs really did get done. */ 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anyMark = False; 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = specs; sp; sp = sp->next) { 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp->done = False; 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp->mark = VG_(string_match)( sp->from_sopatt, 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_get_soname)(di) ); 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anyMark = anyMark || sp->mark; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* shortcut: if none of the sonames match, there will be no bindings. */ 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!anyMark) 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Iterate outermost over the symbols in the seginfo, in the hope 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of trashing the caches less. */ 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nsyms = VG_(DebugInfo_syms_howmany)( di ); 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nsyms; i++) { 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_syms_getidx)( di, i, &sym_addr, NULL, NULL, 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &sym_name, &isText, &isIFunc ); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ignore data symbols */ 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!isText) 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* On AIX, we cannot redirect calls to a so-called glink 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown function for reasons which are not obvious - something to do 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with saving r2 across the call. Not a problem, as we don't 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown want to anyway; presumably it is the target of the glink we 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown need to redirect. Hence just spot them and ignore them. 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown They are always of a very specific (more or less 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ABI-mandated) form. */ 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_aix5_glink_idiom(sym_addr)) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = specs; sp; sp = sp->next) { 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sp->mark) 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; /* soname doesn't match */ 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(string_match)( sp->from_fnpatt, sym_name )) { 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* got a new binding. Add to collection. */ 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.from_addr = sym_addr; 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.to_addr = sp->to_addr; 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.parent_spec = parent_spec; 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.parent_sym = parent_sym; 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.isWrap = sp->isWrap; 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.isIFunc = isIFunc; 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp->done = True; 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown maybe_add_active( act ); 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* for (sp = specs; sp; sp = sp->next) */ 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* for (i = 0; i < nsyms; i++) */ 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now, finally, look for Specs which were marked to be done, but 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown didn't get matched. If any such are mandatory we must abort the 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown system at this point. */ 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = specs; sp; sp = sp->next) { 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sp->mark) 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp->mark && (!sp->done) && sp->mandatory) 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp) { 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar** strp; 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* v = "valgrind: "; 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sp->mark); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!sp->done); 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sp->mandatory); 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sFatal error at startup: a function redirection\n", v); 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%swhich is mandatory for this platform-tool combination\n", v); 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%scannot be set up. Details of the redirection are:\n", v); 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s\n", v); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sA must-be-redirected function\n", v); 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%swhose name matches the pattern: %s\n", v, sp->from_fnpatt); 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sin an object with soname matching: %s\n", v, sp->from_sopatt); 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%swas not found whilst processing\n", v); 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%ssymbols from the object with soname: %s\n", 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v, VG_(DebugInfo_get_soname)(di)); 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s\n", v); 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (strp = sp->mandatory; *strp; strp++) 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s%s\n", v, *strp); 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s\n", v); 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sCannot continue -- exiting now. Sorry.\n", v); 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add an act (passed by value; is copied here) and deal with 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown conflicting bindings. */ 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void maybe_add_active ( Active act ) 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* what = NULL; 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* old; 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Complain and ignore manifestly bogus 'from' addresses. 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Kludge: because this can get called befor the trampoline area (a 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bunch of magic 'to' addresses) has its ownership changed from V 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to C, we can't check the 'to' address similarly. Sigh. 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64-linux hack: the vsysinfo pages appear to have no 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown permissions 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so skip the check for them. */ 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_plausible_guest_addr(act.from_addr) 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_amd64_linux) 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act.from_addr != 0xFFFFFFFFFF600000ULL 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act.from_addr != 0xFFFFFFFFFF600400ULL 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) { 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what = "redirection from-address is in non-executable area"; 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr ); 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old) { 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Dodgy. Conflicting binding. */ 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(old->from_addr == act.from_addr); 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (old->to_addr != act.to_addr) { 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we have to ignore it -- otherwise activeSet would contain 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown conflicting bindings. */ 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what = "new redirection conflicts with existing -- ignoring it"; 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This appears to be a duplicate of an existing binding. 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Safe(ish) -- ignore. */ 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* XXXXXXXXXXX COMPLAIN if new and old parents differ */ 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active)); 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a); 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *a = act; 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_Insert)(activeSet, a); 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now that a new from->to redirection is in force, we need to 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get rid of any translations intersecting 'from' in order that 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they get redirected to 'to'. So discard them. Just for 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown paranoia (but, I believe, unnecessarily), discard 'to' as 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown well. */ 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act.from_addr, 1, 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_new_DebugInfo(from_addr)"); 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act.to_addr, 1, 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_new_DebugInfo(to_addr)"); 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad: 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(what); 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) { 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "WARNING: %s\n", what); 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_active( " new: ", &act); 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notify m_redir of the deletion of a DebugInfo. This is relatively 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simple -- just get rid of all actives derived from it, and free up 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the associated list elements. */ 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_notify_delete_DebugInfo)( DebugInfo* delsi ) 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* ts; 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* tsPrev; 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp; 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp_next; 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OSet* tmpSet; 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* act; 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool delMe; 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr addr; 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(delsi); 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Search for it, and make tsPrev point to the previous entry, if 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any. */ 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsPrev = NULL; 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts = topSpecs; 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ts == NULL) break; 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ts->seginfo == delsi) break; 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsPrev = ts; 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts = ts->next; 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ts); /* else we don't have the deleted DebugInfo */ 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ts->seginfo == delsi); 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Traverse the actives, copying the addresses of those we intend 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to delete into tmpSet. */ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpSet = VG_(OSetWord_Create)(dinfo_zalloc, "redir.rndD.1", dinfo_free); 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts->mark = True; 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)( activeSet ); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (act = VG_(OSetGen_Next)(activeSet)) ) { 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delMe = act->parent_spec != NULL 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_sym != NULL 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_spec->seginfo != NULL 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_sym->seginfo != NULL 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (act->parent_spec->mark || act->parent_sym->mark); 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* While we're at it, a bit of paranoia: delete any actives 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which don't have both feet in valid client executable areas. 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown But don't delete hardwired-at-startup ones; these are denoted 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by having parent_spec or parent_sym being NULL. */ 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (!delMe) 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_spec != NULL 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && act->parent_sym != NULL ) { 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_plausible_guest_addr(act->from_addr)) 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delMe = True; 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!is_plausible_guest_addr(act->to_addr)) 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delMe = True; 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (delMe) { 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetWord_Insert)( tmpSet, act->from_addr ); 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* While we have our hands on both the 'from' and 'to' 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of this Active, do paranoid stuff with tt/tc. */ 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act->from_addr, 1, 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_del_DebugInfo(from_addr)"); 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( (Addr64)act->to_addr, 1, 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir_del_DebugInfo(to_addr)"); 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now traverse tmpSet, deleting corresponding elements in activeSet. */ 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetWord_ResetIter)( tmpSet ); 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( VG_(OSetWord_Next)(tmpSet, &addr) ) { 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act = VG_(OSetGen_Remove)( activeSet, &addr ); 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(act); 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_FreeNode)( activeSet, act ); 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetWord_Destroy)( tmpSet ); 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The Actives set is now cleaned up. Free up this TopSpec and 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown everything hanging off it. */ 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = ts->specs; sp; sp = sp_next) { 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp->from_sopatt) dinfo_free(sp->from_sopatt); 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sp->from_fnpatt) dinfo_free(sp->from_fnpatt); 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sp_next = sp->next; 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_free(sp); 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tsPrev == NULL) { 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first in list */ 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs = ts->next; 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tsPrev->next = ts->next; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_free(ts); 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_redir_state("after VG_(redir_notify_delete_DebugInfo)"); 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- QUERIES (really the whole point of this module) ---*/ 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the crucial redirection function. It answers the question: 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should this code address be redirected somewhere else? It's used 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown just before translating a basic block. */ 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap ) 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* r = VG_(OSetGen_Lookup)(activeSet, &orig); 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (r == NULL) 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return orig; 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(r->to_addr != 0); 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (isWrap) 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *isWrap = r->isWrap || r->isIFunc; 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (r->isIFunc) { 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(iFuncWrapper); 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iFuncWrapper; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r->to_addr; 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- INITIALISATION ---*/ 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a never-delete-me Active. */ 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) /* only used on amd64 */ 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_hardwired_active ( Addr from, Addr to ) 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active act; 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.from_addr = from; 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.to_addr = to; 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.parent_spec = NULL; 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.parent_sym = NULL; 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.isWrap = False; 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act.isIFunc = False; 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown maybe_add_active( act ); 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a never-delete-me Spec. This is a bit of a kludge. On the 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assumption that this is called only at startup, only handle the 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case where topSpecs is completely empty, or if it isn't, it has 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown just one entry and that is the one with NULL seginfo -- that is the 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entry that holds these initial specs. */ 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) /* not used on all platforms */ 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_hardwired_spec ( HChar* sopatt, HChar* fnpatt, 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr to_addr, 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar** mandatory ) 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec)); 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(spec); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (topSpecs == NULL) { 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs = dinfo_zalloc("redir.ahs.2", sizeof(TopSpec)); 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs); 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* symtab_zalloc sets all fields to zero */ 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs != NULL); 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs->next == NULL); 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(topSpecs->seginfo == NULL); 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXED PARTS */ 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->from_sopatt = sopatt; 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->from_fnpatt = fnpatt; 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->to_addr = to_addr; 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->isWrap = False; 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->mandatory = mandatory; 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VARIABLE PARTS */ 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->mark = False; /* not significant */ 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->done = False; /* not significant */ 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->next = topSpecs->specs; 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown topSpecs->specs = spec; 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((unused)) /* not used on all platforms */ 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const HChar* complain_about_stripped_glibc_ldso[] 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown= { "Possible fixes: (1, short term): install glibc's debuginfo", 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "package on this machine. (2, longer term): ask the packagers", 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "for your Linux distribution to please in future ship a non-", 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "stripped ld.so (or whatever the dynamic linker .so is called)", 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "that exports the above-named function using the standard", 894f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root "calling conventions for this platform. The package you need", 895f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root "to install for fix (1) is called", 896f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root "", 897f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root " On Debian, Ubuntu: libc6-dbg", 898f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root " On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo", 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown }; 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise the redir system, and create the initial Spec list and 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for amd64-linux a couple of permanent active mappings. The initial 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specs are not converted into Actives yet, on the (checked) 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assumption that no DebugInfos have so far been created, and so when 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown they are created, that will happen. */ 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(redir_initialise) ( void ) 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Assert that there are no DebugInfos so far 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(next_DebugInfo)(NULL) == NULL ); 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Initialise active mapping. 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr), 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, // Use fast comparison 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_zalloc, 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "redir.ri.1", 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dinfo_free); 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The rest of this function just adds initial Specs. 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use this intercept right from the 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */ 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux.so.2", "index", 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_linux_REDIR_FOR_index), 930f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root# if defined(GLIBC_2_2) || defined(GLIBC_2_3) || defined(GLIBC_2_4) \ 931f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root || defined(GLIBC_2_5) || defined(GLIBC_2_6) || defined(GLIBC_2_7) \ 932f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root || defined(GLIBC_2_8) || defined(GLIBC_2_9) \ 933f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root || defined(GLIBC_2_10) || defined(GLIBC_2_11) 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL 935f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root# else 936f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* for glibc-2.12 and later, this is mandatory - can't sanely 937f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root continue without it */ 938f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root complain_about_stripped_glibc_ldso 939f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root# endif 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Redirect vsyscalls to local versions */ 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_active( 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xFFFFFFFFFF600000ULL, 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday) 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_active( 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xFFFFFFFFFF600400ULL, 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_linux_REDIR_FOR_vtime) 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux-x86-64.so.2", "strlen", 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_linux_REDIR_FOR_strlen), 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(GLIBC_2_2) || defined(GLIBC_2_3) || defined(GLIBC_2_4) \ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || defined(GLIBC_2_5) || defined(GLIBC_2_6) || defined(GLIBC_2_7) \ 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || defined(GLIBC_2_8) || defined(GLIBC_2_9) 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* for glibc-2.10 and later, this is mandatory - can't sanely 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue without it */ 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc32_linux) 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is mandatory - can't sanely continue without it */ 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld.so.1", "strlen", 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen), 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld.so.1", "strcmp", 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp), 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL /* not mandatory - so why bother at all? */ 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */ 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld.so.1", "index", 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(ppc32_linux_REDIR_FOR_strchr), 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL /* not mandatory - so why bother at all? */ 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */ 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_linux) 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is mandatory - can't sanely continue without it */ 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld64.so.1", "strlen", 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ), 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld64.so.1", "index", 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strchr) ), 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL /* not mandatory - so why bother at all? */ 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* glibc-2.5 (FC6, ppc64) seems fine without it */ 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_arm_linux) 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise ld.so makes a lot of noise. */ 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux.so.3", "strlen", 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(arm_linux_REDIR_FOR_strlen), 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //add_hardwired_spec( 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // "ld-linux.so.3", "index", 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (Addr)&VG_(arm_linux_REDIR_FOR_index), 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // NULL 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //); 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec( 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "ld-linux.so.3", "memcpy", 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(arm_linux_REDIR_FOR_memcpy), 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complain_about_stripped_glibc_ldso 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* nothing so far */ 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc32_aix5) 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* nothing so far */ 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_aix5) 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* nothing so far */ 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise dyld makes a lot of noise. */ 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcmp", 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strcmp), NULL); 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlen", 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strlen), NULL); 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcat", 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strcat), NULL); 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcpy", 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strcpy), NULL); 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlcat", 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(x86_darwin_REDIR_FOR_strlcat), NULL); 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're using memcheck, use these intercepts right from 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the start, otherwise dyld makes a lot of noise. */ 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcmp", 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strcmp), NULL); 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlen", 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strlen), NULL); 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcat", 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strcat), NULL); 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strcpy", 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strcpy), NULL); 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "strlcat", 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_strlcat), NULL); 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: #warning fixme rdar://6166275 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_hardwired_spec("dyld", "arc4random", 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr)&VG_(amd64_darwin_REDIR_FOR_arc4random), NULL); 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown platform 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_redir)) 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_redir_state("after VG_(redir_initialise)"); 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- MISC HELPERS ---*/ 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* dinfo_zalloc(HChar* ec, SizeT n) { 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* p; 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n > 0); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = VG_(arena_malloc)(VG_AR_DINFO, ec, n); 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(p); 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(p, 0, n); 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return p; 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void dinfo_free(void* p) { 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(p); 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_free)(VG_AR_DINFO, p); 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* dinfo_strdup(HChar* ec, HChar* str) 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_strdup)(VG_AR_DINFO, ec, str); 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Really this should be merged with translations_allowable_from_seg 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in m_translate. */ 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_plausible_guest_addr(Addr a) 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NSegment const* seg = VG_(am_find_nsegment)(a); 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return seg != NULL 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (seg->kind == SkAnonC || seg->kind == SkFileC) 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (seg->hasX || seg->hasR); /* crude x86-specific hack */ 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A function which spots AIX 'glink' functions. A 'glink' function 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is a stub function which has something to do with AIX-style dynamic 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown linking, and jumps to the real target (with which it typically 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shares the same name). See also comment where this function is 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used (above). */ 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_aix5_glink_idiom ( Addr sym_addr ) 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_ppc32_aix5) 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt* w = (UInt*)sym_addr; 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_IS_4_ALIGNED(w) 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && is_plausible_guest_addr((Addr)(w+0)) 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && is_plausible_guest_addr((Addr)(w+6)) 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (w[0] & 0xFFFF0000) == 0x81820000 /* lwz r12,func@toc(r2) */ 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[1] == 0x90410014 /* stw r2,20(r1) */ 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[2] == 0x800c0000 /* lwz r0,0(r12) */ 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[3] == 0x804c0004 /* lwz r2,4(r12) */ 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[4] == 0x7c0903a6 /* mtctr r0 */ 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[5] == 0x4e800420 /* bctr */ 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[6] == 0x00000000 /* illegal */) 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_ppc64_aix5) 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt* w = (UInt*)sym_addr; 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_IS_4_ALIGNED(w) 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && is_plausible_guest_addr((Addr)(w+0)) 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && is_plausible_guest_addr((Addr)(w+6)) 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (w[0] & 0xFFFF0000) == 0xE9820000 /* ld r12,func@toc(r2) */ 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[1] == 0xF8410028 /* std r2,40(r1) */ 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[2] == 0xE80C0000 /* ld r0,0(r12) */ 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[3] == 0xE84C0008 /* ld r2,8(r12) */ 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[4] == 0x7c0903a6 /* mtctr r0 */ 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[5] == 0x4e800420 /* bctr */ 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && w[6] == 0x00000000 /* illegal */) 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NOTIFY-ON-LOAD FUNCTIONS ---*/ 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid handle_maybe_load_notifier( const UChar* soname, 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* symbol, Addr addr ) 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* x86-linux only: if we see _dl_sysinfo_int80, note its address. 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See comment on declaration of VG_(client__dl_sysinfo_int80) for 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the reason. As far as I can tell, the relevant symbol is always 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in object with soname "ld-linux.so.2". */ 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (symbol && symbol[0] == '_' 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == VG_(strcmp)(symbol, "_dl_sysinfo_int80") 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == VG_(strcmp)(soname, "ld-linux.so.2")) { 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(client__dl_sysinfo_int80) == 0) 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client__dl_sysinfo_int80) = addr; 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Normal load-notifier handling after here. First, ignore all 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols lacking the right prefix. */ 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 != VG_(strncmp)(symbol, VG_NOTIFY_ON_LOAD_PREFIX, 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_NOTIFY_ON_LOAD_PREFIX_LEN)) 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't have the right prefix */ 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0) 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client___libc_freeres_wrapper) = addr; 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0) 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iFuncWrapper = addr; 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "unrecognised load notification function: %s", symbol); 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- REQUIRE-TEXT-SYMBOL HANDLING ---*/ 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In short: check that the currently-being-loaded object has text 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown symbols that satisfy any --require-text-symbol= specifications that 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown apply to it, and abort the run with an error message if not. 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_require_text_symbols ( DebugInfo* di ) 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First thing to do is figure out which, if any, 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --require-text-symbol specification strings apply to this 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object. Most likely none do, since it is not expected to 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frequently be used. Work through the list of specs and 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accumulate in fnpatts[] the fn patterns that pertain to this 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object. */ 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnpatts[VG_CLO_MAX_REQ_TSYMS]; 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int fnpatts_used = 0; 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, j; 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar* di_soname = VG_(DebugInfo_get_soname)(di); 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(di_soname); // must be present 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&fnpatts, 0, sizeof(fnpatts)); 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(clo_n_req_tsyms) >= 0); 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(clo_n_req_tsyms) <= VG_CLO_MAX_REQ_TSYMS); 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_(clo_n_req_tsyms); i++) { 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* spec = VG_(clo_req_tsyms)[i]; 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(spec && VG_(strlen)(spec) >= 4); 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // clone the spec, so we can stick a zero at the end of the sopatt 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec = VG_(strdup)("m_redir.hrts.1", spec); 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar sep = spec[0]; 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* sopatt = &spec[1]; 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnpatt = VG_(strchr)(sopatt, sep); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the initial check at clo processing in time in m_main 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // should ensure this. 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(fnpatt && *fnpatt == sep); 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *fnpatt = 0; 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnpatt++; 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(string_match)(sopatt, di_soname)) 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fnpatts[fnpatts_used++] 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(strdup)("m_redir.hrts.2", fnpatt); 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(spec); 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fnpatts_used == 0) 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; /* no applicable spec strings */ 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So finally, fnpatts[0 .. fnpatts_used - 1] contains the set of 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (patterns for) text symbol names that must be found in this 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown object, in order to continue. That is, we must find at least 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown one text symbol name that matches each pattern, else we must 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown abort the run. */ 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("for %s\n", di_soname); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fnpatts_used; i++) 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)(" fnpatt: %s\n", fnpatts[i]); 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For each spec, look through the syms to find one that matches. 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This isn't terribly efficient but it happens rarely, so no big 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown deal. */ 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fnpatts_used; i++) { 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found = False; 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnpatt = fnpatts[i]; 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nsyms = VG_(DebugInfo_syms_howmany)(di); 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < nsyms; j++) { 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isText = False; 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* sym_name = NULL; 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(DebugInfo_syms_getidx)( di, j, NULL, NULL, 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, &sym_name, &isText, NULL ); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ignore data symbols */ 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("QQQ %s\n", sym_name); 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sym_name); 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!isText) 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(string_match)(fnpatt, sym_name)) { 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = True; 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found) { 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* v = "valgrind: "; 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sFatal error at when loading library with soname\n", v); 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s %s\n", v, di_soname); 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sCannot find any text symbol with a name " 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "that matches the pattern\n", v); 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%s %s\n", v, fnpatt); 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%sas required by a --require-text-symbol= " 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "specification.\n", v); 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%sCannot continue -- exiting now.\n", v); 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All required specs were found. Just free memory and return. */ 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < fnpatts_used; i++) 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(fnpatts[i]); 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- SANITY/DEBUG ---*/ 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void show_spec ( HChar* left, Spec* spec ) 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_DebugMsg, 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s%25s %30s %s-> 0x%08llx\n", 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown left, 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->from_sopatt, spec->from_fnpatt, 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spec->isWrap ? "W" : "R", 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)spec->to_addr ); 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void show_active ( HChar* left, Active* act ) 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok; 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar name1[64] = ""; 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar name2[64] = ""; 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name1[0] = name2[0] = 0; 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(get_fnname_w_offset)(act->from_addr, name1, 64); 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) VG_(strcpy)(name1, "???"); 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok = VG_(get_fnname_w_offset)(act->to_addr, name2, 64); 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) VG_(strcpy)(name2, "???"); 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> 0x%08llx %s\n", 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown left, 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)act->from_addr, name1, 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown act->isWrap ? "W" : "R", 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)act->to_addr, name2 ); 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void show_redir_state ( HChar* who ) 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TopSpec* ts; 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Spec* sp; 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Active* act; 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "<<\n"); 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " ------ REDIR STATE %s ------\n", who); 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (ts = topSpecs; ts; ts = ts->next) { 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " TOPSPECS of soname %s\n", 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ts->seginfo 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? (HChar*)VG_(DebugInfo_get_soname)(ts->seginfo) 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : "(hardwired)" ); 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (sp = ts->specs; sp; sp = sp->next) 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_spec(" ", sp); 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------\n"); 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(OSetGen_ResetIter)( activeSet ); 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (act = VG_(OSetGen_Next)(activeSet)) ) { 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show_active(" ", act); 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, ">>\n"); 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1366