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