Home | History | Annotate | Download | only in coregrind
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Function replacement and wrapping.                 m_redir.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2000-2013 Julian Seward
     11       jseward (at) acm.org
     12    Copyright (C) 2003-2013 Jeremy Fitzhardinge
     13       jeremy (at) goop.org
     14 
     15    This program is free software; you can redistribute it and/or
     16    modify it under the terms of the GNU General Public License as
     17    published by the Free Software Foundation; either version 2 of the
     18    License, or (at your option) any later version.
     19 
     20    This program is distributed in the hope that it will be useful, but
     21    WITHOUT ANY WARRANTY; without even the implied warranty of
     22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     23    General Public License for more details.
     24 
     25    You should have received a copy of the GNU General Public License
     26    along with this program; if not, write to the Free Software
     27    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     28    02111-1307, USA.
     29 
     30    The GNU General Public License is contained in the file COPYING.
     31 */
     32 
     33 #include "pub_core_basics.h"
     34 #include "pub_core_debuglog.h"
     35 #include "pub_core_debuginfo.h"
     36 #include "pub_core_libcbase.h"
     37 #include "pub_core_libcassert.h"
     38 #include "pub_core_libcprint.h"
     39 #include "pub_core_vki.h"
     40 #include "pub_core_libcfile.h"
     41 #include "pub_core_seqmatch.h"
     42 #include "pub_core_mallocfree.h"
     43 #include "pub_core_options.h"
     44 #include "pub_core_oset.h"
     45 #include "pub_core_redir.h"
     46 #include "pub_core_trampoline.h"
     47 #include "pub_core_transtab.h"
     48 #include "pub_core_tooliface.h"    // VG_(needs).malloc_replacement
     49 #include "pub_core_machine.h"      // VG_(fnptr_to_fnentry)
     50 #include "pub_core_aspacemgr.h"    // VG_(am_find_nsegment)
     51 #include "pub_core_xarray.h"
     52 #include "pub_core_clientstate.h"  // VG_(client___libc_freeres_wrapper)
     53 #include "pub_core_demangle.h"     // VG_(maybe_Z_demangle)
     54 #include "pub_core_libcproc.h"     // VG_(libdir)
     55 
     56 #include "config.h" /* GLIBC_MANDATORY_*_REDIRECT */
     57 
     58 
     59 /* This module is a critical part of the redirection/intercept system.
     60    It keeps track of the current intercept state, cleans up the
     61    translation caches when that state changes, and finally, answers
     62    queries about the whether an address is currently redirected or
     63    not.  It doesn't do any of the control-flow trickery needed to put
     64    the redirections into practice.  That is the job of m_translate,
     65    which calls here to find out which translations need to be
     66    redirected.
     67 
     68    The interface is simple.  VG_(redir_initialise) initialises and
     69    loads some hardwired redirects which never disappear; this is
     70    platform-specific.
     71 
     72    The module is notified of redirection state changes by m_debuginfo.
     73    That calls VG_(redir_notify_new_DebugInfo) when a new DebugInfo
     74    (shared object symbol table, basically) appears.  Appearance of new
     75    symbols can cause new (active) redirections to appear for two
     76    reasons: the symbols in the new table may match existing
     77    redirection specifications (see comments below), and because the
     78    symbols in the new table may themselves supply new redirect
     79    specifications which match existing symbols (or ones in the new
     80    table).
     81 
     82    Redirect specifications are really symbols with "funny" prefixes
     83    (_vgrNNNNZU_ and _vgrNNNNZZ_).  These names tell m_redir that the
     84    associated code should replace the standard entry point for some
     85    set of functions.  The set of functions is specified by a (soname
     86    pattern, function name pattern) pair which is encoded in the symbol
     87    name following the prefix.  The names use a Z-encoding scheme so
     88    that they may contain punctuation characters and wildcards (*).
     89    The encoding scheme is described in pub_tool_redir.h and is decoded
     90    by VG_(maybe_Z_demangle).  The NNNN are behavioural equivalence
     91    class tags, and are used to by code in this module to resolve
     92    situations where one address appears to be redirected to more than
     93    one replacement/wrapper.  This is also described in
     94    pub_tool_redir.h.
     95 
     96    When a shared object is unloaded, this module learns of it via a
     97    call to VG_(redir_notify_delete_DebugInfo).  It then removes from
     98    its tables all active redirections in any way associated with that
     99    object, and tidies up the translation caches accordingly.
    100 
    101    That takes care of tracking the redirection state.  When a
    102    translation is actually to be made, m_translate calls to
    103    VG_(redir_do_lookup) in this module to find out if the
    104    translation's address should be redirected.
    105 */
    106 
    107 /*------------------------------------------------------------*/
    108 /*--- Semantics                                            ---*/
    109 /*------------------------------------------------------------*/
    110 
    111 /* The redirector holds two pieces of state:
    112 
    113      Specs  - a set of   (soname pattern, fnname pattern) -> redir addr
    114      Active - a set of   orig addr -> (bool, redir addr)
    115 
    116    Active is the currently active set of bindings that the translator
    117    consults.  Specs is the current set of specifications as harvested
    118    from reading symbol tables of the currently loaded objects.
    119 
    120    Active is a pure function of Specs and the current symbol table
    121    state (maintained by m_debuginfo).  Call the latter SyminfoState.
    122 
    123    Therefore whenever either Specs or SyminfoState changes, Active
    124    must be recomputed.  [Inefficient if done naively, but this is a
    125    spec].
    126 
    127    Active is computed as follows:
    128 
    129       Active = empty
    130       for spec in Specs {
    131          sopatt = spec.soname pattern
    132          fnpatt = spec.fnname pattern
    133          redir  = spec.redir addr
    134          for so matching sopatt in SyminfoState {
    135             for fn matching fnpatt in fnnames_of(so) {
    136                &fn -> redir is added to Active
    137             }
    138          }
    139       }
    140 
    141    [as an implementation detail, when a binding (orig -> redir) is
    142    deleted from Active as a result of recomputing it, then all
    143    translations intersecting redir must be deleted.  However, this is
    144    not part of the spec].
    145 
    146    [Active also depends on where the aspacemgr has decided to put all
    147    the pieces of code -- that affects the "orig addr" and "redir addr"
    148    values.]
    149 
    150    ---------------------
    151 
    152    That completes the spec, apart from one difficult issue: duplicates.
    153 
    154    Clearly we must impose the requirement that domain(Active) contains
    155    no duplicates.  The difficulty is how to constrain Specs enough to
    156    avoid getting into that situation.  It's easy to write specs which
    157    could cause conflicting bindings in Active, eg:
    158 
    159       (libpthread.so, pthread_mutex_lock) ->    a1
    160       (libpthread.so, pthread_*)          ->    a2
    161 
    162    for a1 != a2.  Or even hairier:
    163 
    164       (libpthread.so, pthread_mutex_*) ->    a1
    165       (libpthread.so, pthread_*_lock)  ->    a2
    166 
    167    I can't think of any sane way of detecting when an addition to
    168    Specs would generate conflicts.  However, considering we don't
    169    actually want to have a system that allows this, I propose this:
    170    all changes to Specs are acceptable.  But, when recomputing Active
    171    following the change, if the same orig is bound to more than one
    172    redir, then the first binding for orig is retained, and all the
    173    rest ignored.
    174 
    175    ===========================================================
    176    ===========================================================
    177    Incremental implementation:
    178 
    179    When a new DebugInfo appears:
    180    - it may be the source of new specs
    181    - it may be the source of new matches for existing specs
    182    Therefore:
    183 
    184    - (new Specs x existing DebugInfos): scan all symbols in the new
    185      DebugInfo to find new specs.  Each of these needs to be compared
    186      against all symbols in all the existing DebugInfos to generate
    187      new actives.
    188 
    189    - (existing Specs x new DebugInfo): scan all symbols in the
    190      DebugInfo, trying to match them to any existing specs, also
    191      generating new actives.
    192 
    193    - (new Specs x new DebugInfo): scan all symbols in the new
    194      DebugInfo, trying to match them against the new specs, to
    195      generate new actives.
    196 
    197    - Finally, add new new specs to the current set of specs.
    198 
    199    When adding a new active (s,d) to the Actives:
    200      lookup s in Actives
    201         if already bound to d, ignore
    202         if already bound to something other than d, complain loudly and ignore
    203         else add (s,d) to Actives
    204              and discard (s,1) and (d,1)  (maybe overly conservative)
    205 
    206    When a DebugInfo disappears:
    207    - delete all specs acquired from the seginfo
    208    - delete all actives derived from the just-deleted specs
    209    - if each active (s,d) deleted, discard (s,1) and (d,1)
    210 */
    211 
    212 
    213 /*------------------------------------------------------------*/
    214 /*--- REDIRECTION SPECIFICATIONS                           ---*/
    215 /*------------------------------------------------------------*/
    216 
    217 /* A specification of a redirection we want to do.  Note that because
    218    both the "from" soname and function name may contain wildcards, the
    219    spec can match an arbitrary number of times.
    220 
    221    16 Nov 2007: Comments re .mandatory field: The initial motivation
    222    for this is making Memcheck work sanely on glibc-2.6.X ppc32-linux.
    223    We really need to intercept 'strlen' in ld.so right from startup.
    224    If ld.so does not have a visible 'strlen' symbol, Memcheck
    225    generates an impossible number of errors resulting from highly
    226    tuned strlen implementation in ld.so, and is completely unusable
    227    -- the resulting undefinedness eventually seeps everywhere. */
    228 typedef
    229    struct _Spec {
    230       struct _Spec* next;  /* linked list */
    231       /* FIXED PARTS -- set when created and not changed */
    232       HChar* from_sopatt;  /* from soname pattern  */
    233       HChar* from_fnpatt;  /* from fnname pattern  */
    234       Addr   to_addr;      /* where redirecting to */
    235       Bool   isWrap;       /* wrap or replacement? */
    236       Int    becTag; /* 0 through 9999.  Behavioural equivalance class tag.
    237                         If two wrappers have the same (non-zero) tag, they
    238                         are promising that they behave identically. */
    239       Int    becPrio; /* 0 through 9.  Behavioural equivalence class prio.
    240                          Used to choose between competing wrappers with
    241                          the same (non-zero) tag. */
    242       const HChar** mandatory; /* non-NULL ==> abort V and print the
    243                                   strings if from_sopatt is loaded but
    244                                   from_fnpatt cannot be found */
    245       /* VARIABLE PARTS -- used transiently whilst processing redirections */
    246       Bool   mark; /* set if spec requires further processing */
    247       Bool   done; /* set if spec was successfully matched */
    248    }
    249    Spec;
    250 
    251 /* Top-level data structure.  It contains a pointer to a DebugInfo and
    252    also a list of the specs harvested from that DebugInfo.  Note that
    253    seginfo is allowed to be NULL, meaning that the specs are
    254    pre-loaded ones at startup and are not associated with any
    255    particular seginfo. */
    256 typedef
    257    struct _TopSpec {
    258       struct _TopSpec* next; /* linked list */
    259       const DebugInfo* seginfo;    /* symbols etc */
    260       Spec*      specs;      /* specs pulled out of seginfo */
    261       Bool       mark; /* transient temporary used during deletion */
    262    }
    263    TopSpec;
    264 
    265 /* This is the top level list of redirections.  m_debuginfo maintains
    266    a list of DebugInfos, and the idea here is to maintain a list with
    267    the same number of elements (in fact, with one more element, so as
    268    to record abovementioned preloaded specifications.) */
    269 static TopSpec* topSpecs = NULL;
    270 
    271 
    272 /*------------------------------------------------------------*/
    273 /*--- CURRENTLY ACTIVE REDIRECTIONS                        ---*/
    274 /*------------------------------------------------------------*/
    275 
    276 /* Represents a currently active binding.  If either parent_spec or
    277    parent_sym is NULL, then this binding was hardwired at startup and
    278    should not be deleted.  Same is true if either parent's seginfo
    279    field is NULL. */
    280 typedef
    281    struct {
    282       Addr     from_addr;   /* old addr -- MUST BE THE FIRST WORD! */
    283       Addr     to_addr;     /* where redirecting to */
    284       TopSpec* parent_spec; /* the TopSpec which supplied the Spec */
    285       TopSpec* parent_sym;  /* the TopSpec which supplied the symbol */
    286       Int      becTag;      /* behavioural eclass tag for ::to_addr */
    287       Int      becPrio;     /* and its priority */
    288       Bool     isWrap;      /* wrap or replacement? */
    289       Bool     isIFunc;     /* indirect function? */
    290    }
    291    Active;
    292 
    293 /* The active set is a fast lookup table */
    294 static OSet* activeSet = NULL;
    295 
    296 /* Wrapper routine for indirect functions */
    297 static Addr iFuncWrapper;
    298 
    299 /*------------------------------------------------------------*/
    300 /*--- FWDses                                               ---*/
    301 /*------------------------------------------------------------*/
    302 
    303 static void maybe_add_active ( Active /*by value; callee copies*/ );
    304 
    305 static void*  dinfo_zalloc(const HChar* ec, SizeT);
    306 static void   dinfo_free(void*);
    307 static HChar* dinfo_strdup(const HChar* ec, const HChar*);
    308 static Bool   is_plausible_guest_addr(Addr);
    309 
    310 static void   show_redir_state ( const HChar* who );
    311 static void   show_active ( const HChar* left, const Active* act );
    312 
    313 static void   handle_maybe_load_notifier( const HChar* soname,
    314                                           const HChar* symbol, Addr addr );
    315 
    316 static void   handle_require_text_symbols ( const DebugInfo* );
    317 
    318 /*------------------------------------------------------------*/
    319 /*--- NOTIFICATIONS                                        ---*/
    320 /*------------------------------------------------------------*/
    321 
    322 static
    323 void generate_and_add_actives (
    324         /* spec list and the owning TopSpec */
    325         Spec*    specs,
    326         TopSpec* parent_spec,
    327 	/* debuginfo and the owning TopSpec */
    328         const DebugInfo* di,
    329         TopSpec* parent_sym
    330      );
    331 
    332 
    333 /* Copy all the names from a given symbol into an AR_DINFO allocated,
    334    NULL terminated array, for easy iteration.  Caller must pass also
    335    the address of a 2-entry array which can be used in the common case
    336    to avoid dynamic allocation. */
    337 static const HChar** alloc_symname_array ( const HChar* pri_name,
    338                                            const HChar** sec_names,
    339                                            const HChar** twoslots )
    340 {
    341    /* Special-case the common case: only one name.  We expect the
    342       caller to supply a stack-allocated 2-entry array for this. */
    343    if (sec_names == NULL) {
    344       twoslots[0] = pri_name;
    345       twoslots[1] = NULL;
    346       return twoslots;
    347    }
    348    /* Else must use dynamic allocation.  Figure out size .. */
    349    Word    n_req = 1;
    350    const HChar** pp = sec_names;
    351    while (*pp) { n_req++; pp++; }
    352    /* .. allocate and copy in. */
    353    const HChar** arr = dinfo_zalloc("redir.asa.1", (n_req+1) * sizeof(HChar*));
    354    Word    i   = 0;
    355    arr[i++] = pri_name;
    356    pp = sec_names;
    357    while (*pp) { arr[i++] = *pp; pp++; }
    358    vg_assert(i == n_req);
    359    vg_assert(arr[n_req] == NULL);
    360    return arr;
    361 }
    362 
    363 
    364 /* Free the array allocated by alloc_symname_array, if any. */
    365 static void free_symname_array ( const HChar** names, const HChar** twoslots )
    366 {
    367    if (names != twoslots)
    368       dinfo_free(names);
    369 }
    370 
    371 static HChar const* advance_to_equal ( HChar const* c ) {
    372    while (*c && *c != '=') {
    373       ++c;
    374    }
    375    return c;
    376 }
    377 static HChar const* advance_to_comma ( HChar const* c ) {
    378    while (*c && *c != ',') {
    379       ++c;
    380    }
    381    return c;
    382 }
    383 
    384 /* Notify m_redir of the arrival of a new DebugInfo.  This is fairly
    385    complex, but the net effect is to (1) add a new entry to the
    386    topspecs list, and (2) figure out what new binding are now active,
    387    and, as a result, add them to the actives mapping. */
    388 
    389 void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi )
    390 {
    391    Bool         ok, isWrap;
    392    Int          i, nsyms, becTag, becPrio;
    393    Spec*        specList;
    394    Spec*        spec;
    395    TopSpec*     ts;
    396    TopSpec*     newts;
    397    const HChar*  sym_name_pri;
    398    const HChar** sym_names_sec;
    399    SymAVMAs     sym_avmas;
    400    const HChar* demangled_sopatt;
    401    const HChar* demangled_fnpatt;
    402    Bool         check_ppcTOCs = False;
    403    Bool         isText;
    404    const HChar* newdi_soname;
    405    Bool         dehacktivate_pthread_stack_cache_var_search = False;
    406    const HChar* const pthread_soname = "libpthread.so.0";
    407    const HChar* const pthread_stack_cache_actsize_varname
    408       = "stack_cache_actsize";
    409 
    410 #  if defined(VG_PLAT_USES_PPCTOC)
    411    check_ppcTOCs = True;
    412 #  endif
    413 
    414    vg_assert(newdi);
    415    newdi_soname = VG_(DebugInfo_get_soname)(newdi);
    416    vg_assert(newdi_soname != NULL);
    417 
    418 #ifdef ENABLE_INNER
    419    {
    420       /* When an outer Valgrind is executing an inner Valgrind, the
    421          inner "sees" in its address space the mmap-ed vgpreload files
    422          of the outer.  The inner must avoid interpreting the
    423          redirections given in the outer vgpreload mmap-ed files.
    424          Otherwise, some tool combinations badly fail.
    425 
    426          Example: outer memcheck tool executing an inner none tool.
    427 
    428          If inner none interprets the outer malloc redirection, the
    429          inner will redirect malloc to a memcheck function it does not
    430          have (as the redirection target is from the outer).  With
    431          such a failed redirection, a call to malloc inside the inner
    432          will then result in a "no-operation" (and so no memory will
    433          be allocated).
    434 
    435          When running as an inner, no redirection will be done
    436          for a vgpreload file if this file is not located in the
    437          inner VALGRIND_LIB directory.
    438 
    439          Recognising a vgpreload file based on a filename pattern
    440          is a kludge. An alternate solution would be to change
    441          the _vgr prefix according to outer/inner/client.
    442       */
    443       const HChar* newdi_filename = VG_(DebugInfo_get_filename)(newdi);
    444       const HChar* newdi_basename = VG_(basename) (newdi_filename);
    445       if (VG_(strncmp) (newdi_basename, "vgpreload_", 10) == 0) {
    446          /* This looks like a vgpreload file => check if this file
    447             is from the inner VALGRIND_LIB.
    448             We do this check using VG_(stat) + dev/inode comparison
    449             as vg-in-place defines a VALGRIND_LIB with symlinks
    450             pointing to files inside the valgrind build directories. */
    451          struct vg_stat newdi_stat;
    452          SysRes newdi_res;
    453          struct vg_stat in_vglib_stat;
    454          SysRes in_vglib_res;
    455 
    456          newdi_res = VG_(stat)(newdi_filename, &newdi_stat);
    457 
    458          HChar in_vglib_filename[VG_(strlen)(VG_(libdir)) + 1 +
    459                                  VG_(strlen)(newdi_basename) + 1];
    460          VG_(sprintf)(in_vglib_filename, "%s/%s", VG_(libdir), newdi_basename);
    461 
    462          in_vglib_res = VG_(stat)(in_vglib_filename, &in_vglib_stat);
    463 
    464          /* If we find newdi_basename in inner VALGRIND_LIB
    465             but newdi_filename is not the same file, then we do
    466             not execute the redirection. */
    467          if (!sr_isError(in_vglib_res)
    468              && !sr_isError(newdi_res)
    469              && (newdi_stat.dev != in_vglib_stat.dev
    470                  || newdi_stat.ino != in_vglib_stat.ino)) {
    471             /* <inner VALGRIND_LIB>/newdi_basename is an existing file
    472                and is different of newdi_filename.
    473                So, we do not execute newdi_filename redirection. */
    474             if ( VG_(clo_verbosity) > 1 ) {
    475                VG_(message)( Vg_DebugMsg,
    476                              "Skipping vgpreload redir in %s"
    477                              " (not from VALGRIND_LIB_INNER)\n",
    478                              newdi_filename);
    479             }
    480             return;
    481          } else {
    482             if ( VG_(clo_verbosity) > 1 ) {
    483                VG_(message)( Vg_DebugMsg,
    484                              "Executing vgpreload redir in %s"
    485                              " (from VALGRIND_LIB_INNER)\n",
    486                              newdi_filename);
    487             }
    488          }
    489       }
    490    }
    491 #endif
    492 
    493 
    494    /* stay sane: we don't already have this. */
    495    for (ts = topSpecs; ts; ts = ts->next)
    496       vg_assert(ts->seginfo != newdi);
    497 
    498    /* scan this DebugInfo's symbol table, pulling out and demangling
    499       any specs found */
    500 
    501    specList = NULL; /* the spec list we're building up */
    502 
    503    dehacktivate_pthread_stack_cache_var_search =
    504       SimHintiS(SimHint_no_nptl_pthread_stackcache, VG_(clo_sim_hints))
    505       && 0 == VG_(strcmp)(newdi_soname, pthread_soname);
    506 
    507    nsyms = VG_(DebugInfo_syms_howmany)( newdi );
    508    for (i = 0; i < nsyms; i++) {
    509       VG_(DebugInfo_syms_getidx)( newdi, i, &sym_avmas,
    510                                   NULL, &sym_name_pri, &sym_names_sec,
    511                                   &isText, NULL );
    512       /* Set up to conveniently iterate over all names for this symbol. */
    513       const HChar*  twoslots[2];
    514       const HChar** names_init =
    515          alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
    516       const HChar** names;
    517       for (names = names_init; *names; names++) {
    518          ok = VG_(maybe_Z_demangle)( *names,
    519                                      &demangled_sopatt,
    520                                      &demangled_fnpatt,
    521                                      &isWrap, &becTag, &becPrio );
    522          /* ignore data symbols */
    523          if (!isText) {
    524             /* But search for dehacktivate stack cache var if needed. */
    525             if (dehacktivate_pthread_stack_cache_var_search
    526                 && 0 == VG_(strcmp)(*names,
    527                                     pthread_stack_cache_actsize_varname)) {
    528                if ( VG_(clo_verbosity) > 1 ) {
    529                   VG_(message)( Vg_DebugMsg,
    530                                 "deactivate nptl pthread stackcache via kludge:"
    531                                 " found symbol %s at addr %p\n",
    532                                 *names, (void*) sym_avmas.main);
    533                }
    534                VG_(client__stack_cache_actsize__addr) = (SizeT*) sym_avmas.main;
    535                dehacktivate_pthread_stack_cache_var_search = False;
    536             }
    537             continue;
    538          }
    539          if (!ok) {
    540             /* It's not a full-scale redirect, but perhaps it is a load-notify
    541                fn?  Let the load-notify department see it. */
    542             handle_maybe_load_notifier( newdi_soname, *names, sym_avmas.main );
    543             continue;
    544          }
    545          if (check_ppcTOCs && GET_TOCPTR_AVMA(sym_avmas) == 0) {
    546             /* This platform uses toc pointers, but none could be found
    547                for this symbol, so we can't safely redirect/wrap to it.
    548                Just skip it; we'll make a second pass over the symbols in
    549                the following loop, and complain at that point. */
    550             continue;
    551          }
    552 
    553          HChar *replaced_sopatt = NULL;
    554          if (0 == VG_(strncmp) (demangled_sopatt,
    555                                 VG_SO_SYN_PREFIX, VG_SO_SYN_PREFIX_LEN)) {
    556             /* This is a redirection for handling lib so synonyms. If we
    557                have a matching lib synonym, then replace the sopatt.
    558                Otherwise, just ignore this redirection spec. */
    559 
    560             if (!VG_(clo_soname_synonyms))
    561                continue; // No synonyms => skip the redir.
    562 
    563             /* Search for a matching synonym=newname*/
    564             SizeT const sopatt_syn_len
    565                = VG_(strlen)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN);
    566             HChar const* last = VG_(clo_soname_synonyms);
    567 
    568             while (*last) {
    569                HChar const* first = last;
    570                last = advance_to_equal(first);
    571 
    572                if ((last - first) == sopatt_syn_len
    573                    && 0 == VG_(strncmp)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN,
    574                                         first,
    575                                         sopatt_syn_len)) {
    576                   // Found the demangle_sopatt synonym => replace it
    577                   first = last + 1;
    578                   last = advance_to_comma(first);
    579                   replaced_sopatt = dinfo_zalloc("redir.rnnD.5",
    580                                                  last - first + 1);
    581                   VG_(strncpy)(replaced_sopatt, first, last - first);
    582                   replaced_sopatt[last - first] = '\0';
    583                   demangled_sopatt = replaced_sopatt;
    584                   break;
    585                }
    586 
    587                last = advance_to_comma(last);
    588                if (*last == ',')
    589                   last++;
    590             }
    591 
    592             // If we have not replaced the sopatt, then skip the redir.
    593             if (replaced_sopatt == NULL)
    594                continue;
    595          }
    596 
    597          spec = dinfo_zalloc("redir.rnnD.1", sizeof(Spec));
    598          spec->from_sopatt = dinfo_strdup("redir.rnnD.2", demangled_sopatt);
    599          spec->from_fnpatt = dinfo_strdup("redir.rnnD.3", demangled_fnpatt);
    600          spec->to_addr = sym_avmas.main;
    601          spec->isWrap = isWrap;
    602          spec->becTag = becTag;
    603          spec->becPrio = becPrio;
    604          /* check we're not adding manifestly stupid destinations */
    605          vg_assert(is_plausible_guest_addr(sym_avmas.main));
    606          spec->next = specList;
    607          spec->mark = False; /* not significant */
    608          spec->done = False; /* not significant */
    609          specList = spec;
    610       }
    611       free_symname_array(names_init, &twoslots[0]);
    612    }
    613    if (dehacktivate_pthread_stack_cache_var_search) {
    614       VG_(message)(Vg_DebugMsg,
    615                    "WARNING: could not find symbol for var %s in %s\n",
    616                    pthread_stack_cache_actsize_varname, pthread_soname);
    617       VG_(message)(Vg_DebugMsg,
    618                    "=> pthread stack cache cannot be disabled!\n");
    619    }
    620 
    621    if (check_ppcTOCs) {
    622       for (i = 0; i < nsyms; i++) {
    623          VG_(DebugInfo_syms_getidx)( newdi, i, &sym_avmas,
    624                                      NULL, &sym_name_pri, &sym_names_sec,
    625                                      &isText, NULL );
    626          const HChar*  twoslots[2];
    627          const HChar** names_init =
    628             alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
    629          const HChar** names;
    630          for (names = names_init; *names; names++) {
    631             ok = isText
    632                  && VG_(maybe_Z_demangle)(
    633                        *names, &demangled_sopatt,
    634                        &demangled_fnpatt, &isWrap, NULL, NULL );
    635             if (!ok)
    636                /* not a redirect.  Ignore. */
    637                continue;
    638             if (GET_TOCPTR_AVMA(sym_avmas) != 0)
    639                /* has a valid toc pointer.  Ignore. */
    640                continue;
    641 
    642             for (spec = specList; spec; spec = spec->next)
    643                if (0 == VG_(strcmp)(spec->from_sopatt, demangled_sopatt)
    644                    && 0 == VG_(strcmp)(spec->from_fnpatt, demangled_fnpatt))
    645                   break;
    646             if (spec)
    647                /* a redirect to some other copy of that symbol, which
    648                   does have a TOC value, already exists */
    649                continue;
    650 
    651             /* Complain */
    652             VG_(message)(Vg_DebugMsg,
    653                          "WARNING: no TOC ptr for redir/wrap to %s %s\n",
    654                          demangled_sopatt, demangled_fnpatt);
    655          }
    656          free_symname_array(names_init, &twoslots[0]);
    657       }
    658    }
    659 
    660    /* Ok.  Now specList holds the list of specs from the DebugInfo.
    661       Build a new TopSpec, but don't add it to topSpecs yet. */
    662    newts = dinfo_zalloc("redir.rnnD.4", sizeof(TopSpec));
    663    newts->next    = NULL; /* not significant */
    664    newts->seginfo = newdi;
    665    newts->specs   = specList;
    666    newts->mark    = False; /* not significant */
    667 
    668    /* We now need to augment the active set with the following partial
    669       cross product:
    670 
    671       (1) actives formed by matching the new specs in specList against
    672           all symbols currently listed in topSpecs
    673 
    674       (2) actives formed by matching the new symbols in newdi against
    675           all specs currently listed in topSpecs
    676 
    677       (3) actives formed by matching the new symbols in newdi against
    678           the new specs in specList
    679 
    680       This is necessary in order to maintain the invariant that
    681       Actives contains all bindings generated by matching ALL specs in
    682       topSpecs against ALL symbols in topSpecs (that is, a cross
    683       product of ALL known specs against ALL known symbols).
    684    */
    685    /* Case (1) */
    686    for (ts = topSpecs; ts; ts = ts->next) {
    687       if (ts->seginfo)
    688          generate_and_add_actives( specList,    newts,
    689                                    ts->seginfo, ts );
    690    }
    691 
    692    /* Case (2) */
    693    for (ts = topSpecs; ts; ts = ts->next) {
    694       generate_and_add_actives( ts->specs, ts,
    695                                 newdi,     newts );
    696    }
    697 
    698    /* Case (3) */
    699    generate_and_add_actives( specList, newts,
    700                              newdi,    newts );
    701 
    702    /* Finally, add the new TopSpec. */
    703    newts->next = topSpecs;
    704    topSpecs = newts;
    705 
    706    if (VG_(clo_trace_redir))
    707       show_redir_state("after VG_(redir_notify_new_DebugInfo)");
    708 
    709    /* Really finally (quite unrelated to all the above) check the
    710       names in the module against any --require-text-symbol=
    711       specifications we might have. */
    712    handle_require_text_symbols(newdi);
    713 }
    714 
    715 /* Add a new target for an indirect function. Adds a new redirection
    716    for the indirection function with address old_from that redirects
    717    the ordinary function with address new_from to the target address
    718    of the original redirection. */
    719 
    720 void VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from )
    721 {
    722     Active *old, new;
    723 
    724     old = VG_(OSetGen_Lookup)(activeSet, &old_from);
    725     vg_assert(old);
    726     vg_assert(old->isIFunc);
    727 
    728     new = *old;
    729     new.from_addr = new_from;
    730     new.isIFunc = False;
    731     maybe_add_active (new);
    732 
    733     if (VG_(clo_trace_redir)) {
    734        VG_(message)( Vg_DebugMsg,
    735                      "Adding redirect for indirect function "
    736                      "0x%lx from 0x%lx -> 0x%lx\n",
    737                      old_from, new_from, new.to_addr );
    738     }
    739 }
    740 
    741 /* Do one element of the basic cross product: add to the active set,
    742    all matches resulting from comparing all the given specs against
    743    all the symbols in the given seginfo.  If a conflicting binding
    744    would thereby arise, don't add it, but do complain. */
    745 
    746 static
    747 void generate_and_add_actives (
    748         /* spec list and the owning TopSpec */
    749         Spec*    specs,
    750         TopSpec* parent_spec,
    751 	/* seginfo and the owning TopSpec */
    752         const DebugInfo* di,
    753         TopSpec* parent_sym
    754      )
    755 {
    756    Spec*   sp;
    757    Bool    anyMark, isText, isIFunc;
    758    Active  act;
    759    Int     nsyms, i;
    760    SymAVMAs  sym_avmas;
    761    const HChar*  sym_name_pri;
    762    const HChar** sym_names_sec;
    763 
    764    /* First figure out which of the specs match the seginfo's soname.
    765       Also clear the 'done' bits, so that after the main loop below
    766       tell which of the Specs really did get done. */
    767    anyMark = False;
    768    for (sp = specs; sp; sp = sp->next) {
    769       sp->done = False;
    770       sp->mark = VG_(string_match)( sp->from_sopatt,
    771                                     VG_(DebugInfo_get_soname)(di) );
    772       anyMark = anyMark || sp->mark;
    773    }
    774 
    775    /* shortcut: if none of the sonames match, there will be no bindings. */
    776    if (!anyMark)
    777       return;
    778 
    779    /* Iterate outermost over the symbols in the seginfo, in the hope
    780       of trashing the caches less. */
    781    nsyms = VG_(DebugInfo_syms_howmany)( di );
    782    for (i = 0; i < nsyms; i++) {
    783       VG_(DebugInfo_syms_getidx)( di, i, &sym_avmas,
    784                                   NULL, &sym_name_pri, &sym_names_sec,
    785                                   &isText, &isIFunc );
    786       const HChar*  twoslots[2];
    787       const HChar** names_init =
    788          alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
    789       const HChar** names;
    790       for (names = names_init; *names; names++) {
    791 
    792          /* ignore data symbols */
    793          if (!isText)
    794             continue;
    795 
    796          for (sp = specs; sp; sp = sp->next) {
    797             if (!sp->mark)
    798                continue; /* soname doesn't match */
    799             if (VG_(string_match)( sp->from_fnpatt, *names )) {
    800                /* got a new binding.  Add to collection. */
    801                act.from_addr   = sym_avmas.main;
    802                act.to_addr     = sp->to_addr;
    803                act.parent_spec = parent_spec;
    804                act.parent_sym  = parent_sym;
    805                act.becTag      = sp->becTag;
    806                act.becPrio     = sp->becPrio;
    807                act.isWrap      = sp->isWrap;
    808                act.isIFunc     = isIFunc;
    809                sp->done = True;
    810                maybe_add_active( act );
    811 
    812                /* If the function being wrapped has a local entry point
    813                 * redirect it to the global entry point.  The redirection
    814                 * must save and setup r2 then setup r12 for the new function.
    815                 * On return, r2 must be restored.  Local entry points used
    816                 * in PPC64 Little Endian.
    817                 */
    818                if (GET_LOCAL_EP_AVMA(sym_avmas) != 0) {
    819                   act.from_addr = GET_LOCAL_EP_AVMA(sym_avmas);
    820                   maybe_add_active( act );
    821                }
    822 
    823             }
    824          } /* for (sp = specs; sp; sp = sp->next) */
    825 
    826       } /* iterating over names[] */
    827       free_symname_array(names_init, &twoslots[0]);
    828    } /* for (i = 0; i < nsyms; i++)  */
    829 
    830    /* Now, finally, look for Specs which were marked to be done, but
    831       didn't get matched.  If any such are mandatory we must abort the
    832       system at this point. */
    833    for (sp = specs; sp; sp = sp->next) {
    834       if (!sp->mark)
    835          continue;
    836       if (sp->mark && (!sp->done) && sp->mandatory)
    837          break;
    838    }
    839    if (sp) {
    840       const HChar** strp;
    841       const HChar* v = "valgrind:  ";
    842       vg_assert(sp->mark);
    843       vg_assert(!sp->done);
    844       vg_assert(sp->mandatory);
    845       VG_(printf)("\n");
    846       VG_(printf)(
    847       "%sFatal error at startup: a function redirection\n", v);
    848       VG_(printf)(
    849       "%swhich is mandatory for this platform-tool combination\n", v);
    850       VG_(printf)(
    851       "%scannot be set up.  Details of the redirection are:\n", v);
    852       VG_(printf)(
    853       "%s\n", v);
    854       VG_(printf)(
    855       "%sA must-be-redirected function\n", v);
    856       VG_(printf)(
    857       "%swhose name matches the pattern:      %s\n", v, sp->from_fnpatt);
    858       VG_(printf)(
    859       "%sin an object with soname matching:   %s\n", v, sp->from_sopatt);
    860       VG_(printf)(
    861       "%swas not found whilst processing\n", v);
    862       VG_(printf)(
    863       "%ssymbols from the object with soname: %s\n",
    864       v, VG_(DebugInfo_get_soname)(di));
    865       VG_(printf)(
    866       "%s\n", v);
    867 
    868       for (strp = sp->mandatory; *strp; strp++)
    869          VG_(printf)(
    870          "%s%s\n", v, *strp);
    871 
    872       VG_(printf)(
    873       "%s\n", v);
    874       VG_(printf)(
    875       "%sCannot continue -- exiting now.  Sorry.\n", v);
    876       VG_(printf)("\n");
    877       VG_(exit)(1);
    878    }
    879 }
    880 
    881 
    882 /* Add an act (passed by value; is copied here) and deal with
    883    conflicting bindings. */
    884 static void maybe_add_active ( Active act )
    885 {
    886    const HChar*  what = NULL;
    887    Active* old     = NULL;
    888    Bool    add_act = False;
    889 
    890    /* Complain and ignore manifestly bogus 'from' addresses.
    891 
    892       Kludge: because this can get called befor the trampoline area (a
    893       bunch of magic 'to' addresses) has its ownership changed from V
    894       to C, we can't check the 'to' address similarly.  Sigh.
    895 
    896       amd64-linux hack: the vsysinfo pages appear to have no
    897       permissions
    898          ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0
    899       so skip the check for them.  */
    900    if (!is_plausible_guest_addr(act.from_addr)
    901 #      if defined(VGP_amd64_linux)
    902        && act.from_addr != 0xFFFFFFFFFF600000ULL
    903        && act.from_addr != 0xFFFFFFFFFF600400ULL
    904        && act.from_addr != 0xFFFFFFFFFF600800ULL
    905 #      endif
    906       ) {
    907       what = "redirection from-address is in non-executable area";
    908       goto bad;
    909    }
    910 
    911    old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr );
    912    if (old) {
    913       /* Dodgy.  Conflicting binding. */
    914       vg_assert(old->from_addr == act.from_addr);
    915       if (old->to_addr != act.to_addr) {
    916          /* We've got a conflicting binding -- that is, from_addr is
    917             specified to redirect to two different destinations,
    918             old->to_addr and act.to_addr.  If we can prove that they
    919             are behaviourally equivalent then that's no problem.  So
    920             we can look at the behavioural eclass tags for both
    921             functions to see if that's so.  If they are equal, and
    922             nonzero, then that's fine.  But if not, we can't show they
    923             are equivalent, so we have to complain, and ignore the new
    924             binding. */
    925          vg_assert(old->becTag  >= 0 && old->becTag  <= 9999);
    926          vg_assert(old->becPrio >= 0 && old->becPrio <= 9);
    927          vg_assert(act.becTag   >= 0 && act.becTag   <= 9999);
    928          vg_assert(act.becPrio  >= 0 && act.becPrio  <= 9);
    929          if (old->becTag == 0)
    930             vg_assert(old->becPrio == 0);
    931          if (act.becTag == 0)
    932             vg_assert(act.becPrio == 0);
    933 
    934          if (old->becTag == 0 || act.becTag == 0 || old->becTag != act.becTag) {
    935             /* We can't show that they are equivalent.  Complain and
    936                ignore. */
    937             what = "new redirection conflicts with existing -- ignoring it";
    938             goto bad;
    939          }
    940          /* They have the same eclass tag.  Use the priorities to
    941             resolve the ambiguity. */
    942          if (act.becPrio <= old->becPrio) {
    943             /* The new one doesn't have a higher priority, so just
    944                ignore it. */
    945             if (VG_(clo_verbosity) > 2) {
    946                VG_(message)(Vg_UserMsg, "Ignoring %s redirection:\n",
    947                             act.becPrio < old->becPrio ? "lower priority"
    948                                                        : "duplicate");
    949                show_active(             "    old: ", old);
    950                show_active(             "    new: ", &act);
    951             }
    952          } else {
    953             /* The tricky case.  The new one has a higher priority, so
    954                we need to get the old one out of the OSet and install
    955                this one in its place. */
    956             if (VG_(clo_verbosity) > 1) {
    957                VG_(message)(Vg_UserMsg,
    958                            "Preferring higher priority redirection:\n");
    959                show_active(             "    old: ", old);
    960                show_active(             "    new: ", &act);
    961             }
    962             add_act = True;
    963             void* oldNd = VG_(OSetGen_Remove)( activeSet, &act.from_addr );
    964             vg_assert(oldNd == old);
    965             VG_(OSetGen_FreeNode)( activeSet, old );
    966             old = NULL;
    967          }
    968       } else {
    969          /* This appears to be a duplicate of an existing binding.
    970             Safe(ish) -- ignore. */
    971          /* XXXXXXXXXXX COMPLAIN if new and old parents differ */
    972       }
    973 
    974    } else {
    975       /* There's no previous binding for this from_addr, so we must
    976          add 'act' to the active set. */
    977       add_act = True;
    978    }
    979 
    980    /* So, finally, actually add it. */
    981    if (add_act) {
    982       Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
    983       vg_assert(a);
    984       *a = act;
    985       VG_(OSetGen_Insert)(activeSet, a);
    986       /* Now that a new from->to redirection is in force, we need to
    987          get rid of any translations intersecting 'from' in order that
    988          they get redirected to 'to'.  So discard them.  Just for
    989          paranoia (but, I believe, unnecessarily), discard 'to' as
    990          well. */
    991       VG_(discard_translations)( act.from_addr, 1,
    992                                  "redir_new_DebugInfo(from_addr)");
    993       VG_(discard_translations)( act.to_addr, 1,
    994                                  "redir_new_DebugInfo(to_addr)");
    995       if (VG_(clo_verbosity) > 2) {
    996          VG_(message)(Vg_UserMsg, "Adding active redirection:\n");
    997          show_active(             "    new: ", &act);
    998       }
    999    }
   1000    return;
   1001 
   1002   bad:
   1003    vg_assert(what);
   1004    vg_assert(!add_act);
   1005    if (VG_(clo_verbosity) > 1) {
   1006       VG_(message)(Vg_UserMsg, "WARNING: %s\n", what);
   1007       if (old) {
   1008          show_active(             "    old: ", old);
   1009       }
   1010       show_active(             "    new: ", &act);
   1011    }
   1012 }
   1013 
   1014 
   1015 /* Notify m_redir of the deletion of a DebugInfo.  This is relatively
   1016    simple -- just get rid of all actives derived from it, and free up
   1017    the associated list elements. */
   1018 
   1019 void VG_(redir_notify_delete_DebugInfo)( const DebugInfo* delsi )
   1020 {
   1021    TopSpec* ts;
   1022    TopSpec* tsPrev;
   1023    Spec*    sp;
   1024    Spec*    sp_next;
   1025    OSet*    tmpSet;
   1026    Active*  act;
   1027    Bool     delMe;
   1028    Addr     addr;
   1029 
   1030    vg_assert(delsi);
   1031 
   1032    /* Search for it, and make tsPrev point to the previous entry, if
   1033       any. */
   1034    tsPrev = NULL;
   1035    ts     = topSpecs;
   1036    while (True) {
   1037      if (ts == NULL) break;
   1038      if (ts->seginfo == delsi) break;
   1039      tsPrev = ts;
   1040      ts = ts->next;
   1041    }
   1042 
   1043    vg_assert(ts); /* else we don't have the deleted DebugInfo */
   1044    vg_assert(ts->seginfo == delsi);
   1045 
   1046    /* Traverse the actives, copying the addresses of those we intend
   1047       to delete into tmpSet. */
   1048    tmpSet = VG_(OSetWord_Create)(dinfo_zalloc, "redir.rndD.1", dinfo_free);
   1049 
   1050    ts->mark = True;
   1051 
   1052    VG_(OSetGen_ResetIter)( activeSet );
   1053    while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
   1054       delMe = act->parent_spec != NULL
   1055               && act->parent_sym != NULL
   1056               && act->parent_spec->seginfo != NULL
   1057               && act->parent_sym->seginfo != NULL
   1058               && (act->parent_spec->mark || act->parent_sym->mark);
   1059 
   1060       /* While we're at it, a bit of paranoia: delete any actives
   1061          which don't have both feet in valid client executable areas.
   1062          But don't delete hardwired-at-startup ones; these are denoted
   1063          by having parent_spec or parent_sym being NULL.  */
   1064       if ( (!delMe)
   1065            && act->parent_spec != NULL
   1066            && act->parent_sym  != NULL ) {
   1067          if (!is_plausible_guest_addr(act->from_addr))
   1068             delMe = True;
   1069          if (!is_plausible_guest_addr(act->to_addr))
   1070             delMe = True;
   1071       }
   1072 
   1073       if (delMe) {
   1074          VG_(OSetWord_Insert)( tmpSet, act->from_addr );
   1075          /* While we have our hands on both the 'from' and 'to'
   1076             of this Active, do paranoid stuff with tt/tc. */
   1077          VG_(discard_translations)( act->from_addr, 1,
   1078                                     "redir_del_DebugInfo(from_addr)");
   1079          VG_(discard_translations)( act->to_addr, 1,
   1080                                     "redir_del_DebugInfo(to_addr)");
   1081       }
   1082    }
   1083 
   1084    /* Now traverse tmpSet, deleting corresponding elements in activeSet. */
   1085    VG_(OSetWord_ResetIter)( tmpSet );
   1086    while ( VG_(OSetWord_Next)(tmpSet, &addr) ) {
   1087       act = VG_(OSetGen_Remove)( activeSet, &addr );
   1088       vg_assert(act);
   1089       VG_(OSetGen_FreeNode)( activeSet, act );
   1090    }
   1091 
   1092    VG_(OSetWord_Destroy)( tmpSet );
   1093 
   1094    /* The Actives set is now cleaned up.  Free up this TopSpec and
   1095       everything hanging off it. */
   1096    for (sp = ts->specs; sp; sp = sp_next) {
   1097       if (sp->from_sopatt) dinfo_free(sp->from_sopatt);
   1098       if (sp->from_fnpatt) dinfo_free(sp->from_fnpatt);
   1099       sp_next = sp->next;
   1100       dinfo_free(sp);
   1101    }
   1102 
   1103    if (tsPrev == NULL) {
   1104       /* first in list */
   1105       topSpecs = ts->next;
   1106    } else {
   1107       tsPrev->next = ts->next;
   1108    }
   1109    dinfo_free(ts);
   1110 
   1111    if (VG_(clo_trace_redir))
   1112       show_redir_state("after VG_(redir_notify_delete_DebugInfo)");
   1113 }
   1114 
   1115 
   1116 /*------------------------------------------------------------*/
   1117 /*--- QUERIES (really the whole point of this module)      ---*/
   1118 /*------------------------------------------------------------*/
   1119 
   1120 /* This is the crucial redirection function.  It answers the question:
   1121    should this code address be redirected somewhere else?  It's used
   1122    just before translating a basic block. */
   1123 Addr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap )
   1124 {
   1125    Active* r = VG_(OSetGen_Lookup)(activeSet, &orig);
   1126    if (r == NULL)
   1127       return orig;
   1128 
   1129    vg_assert(r->to_addr != 0);
   1130    if (isWrap)
   1131       *isWrap = r->isWrap || r->isIFunc;
   1132    if (r->isIFunc) {
   1133       vg_assert(iFuncWrapper);
   1134       return iFuncWrapper;
   1135    }
   1136    return r->to_addr;
   1137 }
   1138 
   1139 
   1140 /*------------------------------------------------------------*/
   1141 /*--- INITIALISATION                                       ---*/
   1142 /*------------------------------------------------------------*/
   1143 
   1144 /* Add a never-delete-me Active. */
   1145 
   1146 __attribute__((unused)) /* only used on amd64 */
   1147 static void add_hardwired_active ( Addr from, Addr to )
   1148 {
   1149    Active act;
   1150    act.from_addr   = from;
   1151    act.to_addr     = to;
   1152    act.parent_spec = NULL;
   1153    act.parent_sym  = NULL;
   1154    act.becTag      = 0; /* "not equivalent to any other fn" */
   1155    act.becPrio     = 0; /* mandatory when becTag == 0 */
   1156    act.isWrap      = False;
   1157    act.isIFunc     = False;
   1158    maybe_add_active( act );
   1159 }
   1160 
   1161 
   1162 /* Add a never-delete-me Spec.  This is a bit of a kludge.  On the
   1163    assumption that this is called only at startup, only handle the
   1164    case where topSpecs is completely empty, or if it isn't, it has
   1165    just one entry and that is the one with NULL seginfo -- that is the
   1166    entry that holds these initial specs. */
   1167 
   1168 __attribute__((unused)) /* not used on all platforms */
   1169 static void add_hardwired_spec (const  HChar* sopatt, const HChar* fnpatt,
   1170                                 Addr   to_addr,
   1171                                 const HChar** mandatory )
   1172 {
   1173    Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec));
   1174 
   1175    if (topSpecs == NULL) {
   1176       topSpecs = dinfo_zalloc("redir.ahs.2", sizeof(TopSpec));
   1177       /* symtab_zalloc sets all fields to zero */
   1178    }
   1179 
   1180    vg_assert(topSpecs != NULL);
   1181    vg_assert(topSpecs->next == NULL);
   1182    vg_assert(topSpecs->seginfo == NULL);
   1183    /* FIXED PARTS */
   1184    /* Note, that these CONST_CAST will not cause a problem, in the sense
   1185       that VG_(redir_notify_delete_DebugInfo) will delete them. The reason
   1186       is that the TopSpec here has seginfo == NULL and such a TopSpec will
   1187       never be freed. See the asserts at the beginning of said function. */
   1188    spec->from_sopatt = CONST_CAST(HChar *,sopatt);
   1189    spec->from_fnpatt = CONST_CAST(HChar *,fnpatt);
   1190    spec->to_addr     = to_addr;
   1191    spec->isWrap      = False;
   1192    spec->mandatory   = mandatory;
   1193    /* VARIABLE PARTS */
   1194    spec->mark        = False; /* not significant */
   1195    spec->done        = False; /* not significant */
   1196 
   1197    spec->next = topSpecs->specs;
   1198    topSpecs->specs = spec;
   1199 }
   1200 
   1201 
   1202 __attribute__((unused)) /* not used on all platforms */
   1203 static const HChar* complain_about_stripped_glibc_ldso[]
   1204 = { "Possible fixes: (1, short term): install glibc's debuginfo",
   1205     "package on this machine.  (2, longer term): ask the packagers",
   1206     "for your Linux distribution to please in future ship a non-",
   1207     "stripped ld.so (or whatever the dynamic linker .so is called)",
   1208     "that exports the above-named function using the standard",
   1209     "calling conventions for this platform.  The package you need",
   1210     "to install for fix (1) is called",
   1211     "",
   1212     "  On Debian, Ubuntu:                 libc6-dbg",
   1213     "  On SuSE, openSuSE, Fedora, RHEL:   glibc-debuginfo",
   1214     NULL
   1215   };
   1216 
   1217 
   1218 /* Initialise the redir system, and create the initial Spec list and
   1219    for amd64-linux a couple of permanent active mappings.  The initial
   1220    Specs are not converted into Actives yet, on the (checked)
   1221    assumption that no DebugInfos have so far been created, and so when
   1222    they are created, that will happen. */
   1223 
   1224 void VG_(redir_initialise) ( void )
   1225 {
   1226    // Assert that there are no DebugInfos so far
   1227    vg_assert( VG_(next_DebugInfo)(NULL) == NULL );
   1228 
   1229    // Initialise active mapping.
   1230    activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr),
   1231                                    NULL,     // Use fast comparison
   1232                                    dinfo_zalloc,
   1233                                    "redir.ri.1",
   1234                                    dinfo_free);
   1235 
   1236    // The rest of this function just adds initial Specs.
   1237 
   1238 #  if defined(VGP_x86_linux)
   1239    /* If we're using memcheck, use this intercept right from the
   1240       start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */
   1241    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1242       const HChar** mandatory;
   1243 #     ifndef GLIBC_MANDATORY_INDEX_AND_STRLEN_REDIRECT
   1244       mandatory = NULL;
   1245 #     else
   1246       /* for glibc-2.12 and later, this is mandatory - can't sanely
   1247          continue without it */
   1248       mandatory = complain_about_stripped_glibc_ldso;
   1249 #     endif
   1250       add_hardwired_spec(
   1251          "ld-linux.so.2", "index",
   1252          (Addr)&VG_(x86_linux_REDIR_FOR_index), mandatory);
   1253       add_hardwired_spec(
   1254          "ld-linux.so.2", "strlen",
   1255          (Addr)&VG_(x86_linux_REDIR_FOR_strlen), mandatory);
   1256    }
   1257 
   1258 #  elif defined(VGP_amd64_linux)
   1259    /* Redirect vsyscalls to local versions */
   1260    add_hardwired_active(
   1261       0xFFFFFFFFFF600000ULL,
   1262       (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday)
   1263    );
   1264    add_hardwired_active(
   1265       0xFFFFFFFFFF600400ULL,
   1266       (Addr)&VG_(amd64_linux_REDIR_FOR_vtime)
   1267    );
   1268    add_hardwired_active(
   1269       0xFFFFFFFFFF600800ULL,
   1270       (Addr)&VG_(amd64_linux_REDIR_FOR_vgetcpu)
   1271    );
   1272 
   1273    /* If we're using memcheck, use these intercepts right from
   1274       the start, otherwise ld.so makes a lot of noise. */
   1275    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1276 
   1277       add_hardwired_spec(
   1278          "ld-linux-x86-64.so.2", "strlen",
   1279          (Addr)&VG_(amd64_linux_REDIR_FOR_strlen),
   1280 #        ifndef GLIBC_MANDATORY_STRLEN_REDIRECT
   1281          NULL
   1282 #        else
   1283          /* for glibc-2.10 and later, this is mandatory - can't sanely
   1284             continue without it */
   1285          complain_about_stripped_glibc_ldso
   1286 #        endif
   1287       );
   1288    }
   1289 
   1290 #  elif defined(VGP_ppc32_linux)
   1291    /* If we're using memcheck, use these intercepts right from
   1292       the start, otherwise ld.so makes a lot of noise. */
   1293    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1294 
   1295       /* this is mandatory - can't sanely continue without it */
   1296       add_hardwired_spec(
   1297          "ld.so.1", "strlen",
   1298          (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen),
   1299          complain_about_stripped_glibc_ldso
   1300       );
   1301       add_hardwired_spec(
   1302          "ld.so.1", "strcmp",
   1303          (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp),
   1304          NULL /* not mandatory - so why bother at all? */
   1305          /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
   1306       );
   1307       add_hardwired_spec(
   1308          "ld.so.1", "index",
   1309          (Addr)&VG_(ppc32_linux_REDIR_FOR_strchr),
   1310          NULL /* not mandatory - so why bother at all? */
   1311          /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
   1312       );
   1313    }
   1314 
   1315 #  elif defined(VGP_ppc64be_linux)
   1316    /* If we're using memcheck, use these intercepts right from
   1317       the start, otherwise ld.so makes a lot of noise. */
   1318    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1319 
   1320       /* this is mandatory - can't sanely continue without it */
   1321       add_hardwired_spec(
   1322          "ld64.so.1", "strlen",
   1323          (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ),
   1324          complain_about_stripped_glibc_ldso
   1325       );
   1326 
   1327       add_hardwired_spec(
   1328          "ld64.so.1", "index",
   1329          (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strchr) ),
   1330          NULL /* not mandatory - so why bother at all? */
   1331          /* glibc-2.5 (FC6, ppc64) seems fine without it */
   1332       );
   1333    }
   1334 
   1335 #  elif defined(VGP_ppc64le_linux)
   1336    /* If we're using memcheck, use these intercepts right from
   1337     * the start, otherwise ld.so makes a lot of noise.
   1338     */
   1339    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1340 
   1341       /* this is mandatory - can't sanely continue without it */
   1342       add_hardwired_spec(
   1343          "ld64.so.2", "strlen",
   1344          (Addr)&VG_(ppc64_linux_REDIR_FOR_strlen),
   1345          complain_about_stripped_glibc_ldso
   1346       );
   1347 
   1348       add_hardwired_spec(
   1349          "ld64.so.2", "index",
   1350          (Addr)&VG_(ppc64_linux_REDIR_FOR_strchr),
   1351          NULL /* not mandatory - so why bother at all? */
   1352          /* glibc-2.5 (FC6, ppc64) seems fine without it */
   1353       );
   1354    }
   1355 
   1356 #  elif defined(VGP_arm_linux)
   1357    /* If we're using memcheck, use these intercepts right from the
   1358       start, otherwise ld.so makes a lot of noise.  In most ARM-linux
   1359       distros, ld.so's soname is ld-linux.so.3, but Ubuntu 14.04 on
   1360       Odroid uses ld-linux-armhf.so.3 for some reason. */
   1361    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1362       /* strlen */
   1363       add_hardwired_spec(
   1364          "ld-linux.so.3", "strlen",
   1365          (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
   1366          complain_about_stripped_glibc_ldso
   1367       );
   1368       add_hardwired_spec(
   1369          "ld-linux-armhf.so.3", "strlen",
   1370          (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
   1371          complain_about_stripped_glibc_ldso
   1372       );
   1373       /* memcpy */
   1374       add_hardwired_spec(
   1375          "ld-linux.so.3", "memcpy",
   1376          (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
   1377          complain_about_stripped_glibc_ldso
   1378       );
   1379       add_hardwired_spec(
   1380          "ld-linux-armhf.so.3", "memcpy",
   1381          (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
   1382          complain_about_stripped_glibc_ldso
   1383       );
   1384       /* strcmp */
   1385       add_hardwired_spec(
   1386          "ld-linux.so.3", "strcmp",
   1387          (Addr)&VG_(arm_linux_REDIR_FOR_strcmp),
   1388          complain_about_stripped_glibc_ldso
   1389       );
   1390       add_hardwired_spec(
   1391          "ld-linux-armhf.so.3", "strcmp",
   1392          (Addr)&VG_(arm_linux_REDIR_FOR_strcmp),
   1393          complain_about_stripped_glibc_ldso
   1394       );
   1395    }
   1396 
   1397 #  elif defined(VGP_arm64_linux)
   1398    /* If we're using memcheck, use these intercepts right from
   1399       the start, otherwise ld.so makes a lot of noise. */
   1400    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1401       add_hardwired_spec(
   1402          "ld-linux-aarch64.so.1", "strlen",
   1403          (Addr)&VG_(arm64_linux_REDIR_FOR_strlen),
   1404          complain_about_stripped_glibc_ldso
   1405       );
   1406       add_hardwired_spec(
   1407          "ld-linux-aarch64.so.1", "index",
   1408          (Addr)&VG_(arm64_linux_REDIR_FOR_index),
   1409          NULL
   1410       );
   1411       add_hardwired_spec(
   1412          "ld-linux-aarch64.so.1", "strcmp",
   1413          (Addr)&VG_(arm64_linux_REDIR_FOR_strcmp),
   1414          NULL
   1415       );
   1416 #     if defined(VGPV_arm64_linux_android)
   1417       add_hardwired_spec(
   1418          "NONE", "__dl_strlen", // in /system/bin/linker64
   1419          (Addr)&VG_(arm64_linux_REDIR_FOR_strlen),
   1420          NULL
   1421       );
   1422 #     endif
   1423    }
   1424 
   1425 #  elif defined(VGP_x86_darwin)
   1426    /* If we're using memcheck, use these intercepts right from
   1427       the start, otherwise dyld makes a lot of noise. */
   1428    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1429       add_hardwired_spec("dyld", "strcmp",
   1430                          (Addr)&VG_(x86_darwin_REDIR_FOR_strcmp), NULL);
   1431       add_hardwired_spec("dyld", "strlen",
   1432                          (Addr)&VG_(x86_darwin_REDIR_FOR_strlen), NULL);
   1433       add_hardwired_spec("dyld", "strcat",
   1434                          (Addr)&VG_(x86_darwin_REDIR_FOR_strcat), NULL);
   1435       add_hardwired_spec("dyld", "strcpy",
   1436                          (Addr)&VG_(x86_darwin_REDIR_FOR_strcpy), NULL);
   1437       add_hardwired_spec("dyld", "strlcat",
   1438                          (Addr)&VG_(x86_darwin_REDIR_FOR_strlcat), NULL);
   1439    }
   1440 
   1441 #  elif defined(VGP_amd64_darwin)
   1442    /* If we're using memcheck, use these intercepts right from
   1443       the start, otherwise dyld makes a lot of noise. */
   1444    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1445       add_hardwired_spec("dyld", "strcmp",
   1446                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strcmp), NULL);
   1447       add_hardwired_spec("dyld", "strlen",
   1448                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strlen), NULL);
   1449       add_hardwired_spec("dyld", "strcat",
   1450                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strcat), NULL);
   1451       add_hardwired_spec("dyld", "strcpy",
   1452                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strcpy), NULL);
   1453       add_hardwired_spec("dyld", "strlcat",
   1454                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strlcat), NULL);
   1455       // DDD: #warning fixme rdar://6166275
   1456       add_hardwired_spec("dyld", "arc4random",
   1457                          (Addr)&VG_(amd64_darwin_REDIR_FOR_arc4random), NULL);
   1458 #     if DARWIN_VERS == DARWIN_10_9
   1459       add_hardwired_spec("dyld", "strchr",
   1460                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strchr), NULL);
   1461 #     endif
   1462    }
   1463 
   1464 #  elif defined(VGP_s390x_linux)
   1465    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1466       // added in rsponse to BZ 327943
   1467       add_hardwired_spec("ld64.so.1", "index",
   1468                          (Addr)&VG_(s390x_linux_REDIR_FOR_index),
   1469                          complain_about_stripped_glibc_ldso);
   1470    }
   1471 
   1472 #  elif defined(VGP_mips32_linux)
   1473    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1474 
   1475       /* this is mandatory - can't sanely continue without it */
   1476       add_hardwired_spec(
   1477          "ld.so.3", "strlen",
   1478          (Addr)&VG_(mips32_linux_REDIR_FOR_strlen),
   1479          complain_about_stripped_glibc_ldso
   1480       );
   1481    }
   1482 
   1483 #  elif defined(VGP_mips64_linux)
   1484    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1485 
   1486       /* this is mandatory - can't sanely continue without it */
   1487       add_hardwired_spec(
   1488          "ld.so.3", "strlen",
   1489          (Addr)&VG_(mips64_linux_REDIR_FOR_strlen),
   1490          complain_about_stripped_glibc_ldso
   1491       );
   1492    }
   1493 
   1494 #  elif defined(VGP_tilegx_linux)
   1495    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1496 
   1497       add_hardwired_spec(
   1498          "ld.so.1", "strlen",
   1499          (Addr)&VG_(tilegx_linux_REDIR_FOR_strlen), NULL
   1500       );
   1501    }
   1502 
   1503 #  else
   1504 #    error Unknown platform
   1505 #  endif
   1506 
   1507    if (VG_(clo_trace_redir))
   1508       show_redir_state("after VG_(redir_initialise)");
   1509 }
   1510 
   1511 
   1512 /*------------------------------------------------------------*/
   1513 /*--- MISC HELPERS                                         ---*/
   1514 /*------------------------------------------------------------*/
   1515 
   1516 static void* dinfo_zalloc(const HChar* ec, SizeT n) {
   1517    void* p;
   1518    vg_assert(n > 0);
   1519    p = VG_(arena_malloc)(VG_AR_DINFO, ec, n);
   1520    VG_(memset)(p, 0, n);
   1521    return p;
   1522 }
   1523 
   1524 static void dinfo_free(void* p) {
   1525    vg_assert(p);
   1526    return VG_(arena_free)(VG_AR_DINFO, p);
   1527 }
   1528 
   1529 static HChar* dinfo_strdup(const HChar* ec, const HChar* str)
   1530 {
   1531    return VG_(arena_strdup)(VG_AR_DINFO, ec, str);
   1532 }
   1533 
   1534 /* Really this should be merged with translations_allowable_from_seg
   1535    in m_translate. */
   1536 static Bool is_plausible_guest_addr(Addr a)
   1537 {
   1538    NSegment const* seg = VG_(am_find_nsegment)(a);
   1539    return seg != NULL
   1540           && (seg->kind == SkAnonC || seg->kind == SkFileC ||
   1541               seg->kind == SkShmC)
   1542           && (seg->hasX || seg->hasR); /* crude x86-specific hack */
   1543 }
   1544 
   1545 
   1546 /*------------------------------------------------------------*/
   1547 /*--- NOTIFY-ON-LOAD FUNCTIONS                             ---*/
   1548 /*------------------------------------------------------------*/
   1549 
   1550 static
   1551 void handle_maybe_load_notifier( const HChar* soname,
   1552                                  const HChar* symbol, Addr addr )
   1553 {
   1554 #  if defined(VGP_x86_linux)
   1555    /* x86-linux only: if we see _dl_sysinfo_int80, note its address.
   1556       See comment on declaration of VG_(client__dl_sysinfo_int80) for
   1557       the reason.  As far as I can tell, the relevant symbol is always
   1558       in object with soname "ld-linux.so.2". */
   1559    if (symbol && symbol[0] == '_'
   1560               && 0 == VG_(strcmp)(symbol, "_dl_sysinfo_int80")
   1561               && 0 == VG_(strcmp)(soname, "ld-linux.so.2")) {
   1562       if (VG_(client__dl_sysinfo_int80) == 0)
   1563          VG_(client__dl_sysinfo_int80) = addr;
   1564    }
   1565 #  endif
   1566 
   1567    /* Normal load-notifier handling after here.  First, ignore all
   1568       symbols lacking the right prefix. */
   1569    vg_assert(symbol); // assert rather than segfault if it is NULL
   1570    if (0 != VG_(strncmp)(symbol, VG_NOTIFY_ON_LOAD_PREFIX,
   1571                                  VG_NOTIFY_ON_LOAD_PREFIX_LEN))
   1572       /* Doesn't have the right prefix */
   1573       return;
   1574 
   1575    if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0)
   1576       VG_(client___libc_freeres_wrapper) = addr;
   1577    else
   1578    if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0)
   1579       iFuncWrapper = addr;
   1580    else
   1581       vg_assert2(0, "unrecognised load notification function: %s", symbol);
   1582 }
   1583 
   1584 
   1585 /*------------------------------------------------------------*/
   1586 /*--- REQUIRE-TEXT-SYMBOL HANDLING                         ---*/
   1587 /*------------------------------------------------------------*/
   1588 
   1589 /* In short: check that the currently-being-loaded object has text
   1590    symbols that satisfy any --require-text-symbol= specifications that
   1591    apply to it, and abort the run with an error message if not.
   1592 */
   1593 static void handle_require_text_symbols ( const DebugInfo* di )
   1594 {
   1595    /* First thing to do is figure out which, if any,
   1596       --require-text-symbol specification strings apply to this
   1597       object.  Most likely none do, since it is not expected to
   1598       frequently be used.  Work through the list of specs and
   1599       accumulate in fnpatts[] the fn patterns that pertain to this
   1600       object. */
   1601    XArray *fnpatts = VG_(newXA)( VG_(malloc), "m_redir.hrts.5",
   1602                                  VG_(free), sizeof(HChar*) );
   1603 
   1604    Int    i, j;
   1605    const HChar* di_soname = VG_(DebugInfo_get_soname)(di);
   1606    vg_assert(di_soname); // must be present
   1607 
   1608    for (i = 0; i < VG_(sizeXA)(VG_(clo_req_tsyms)); i++) {
   1609       const HChar* clo_spec = *(HChar**) VG_(indexXA)(VG_(clo_req_tsyms), i);
   1610       vg_assert(clo_spec && VG_(strlen)(clo_spec) >= 4);
   1611       // clone the spec, so we can stick a zero at the end of the sopatt
   1612       HChar *spec = VG_(strdup)("m_redir.hrts.1", clo_spec);
   1613       HChar sep = spec[0];
   1614       HChar* sopatt = &spec[1];
   1615       HChar* fnpatt = VG_(strchr)(sopatt, sep);
   1616       // the initial check at clo processing in time in m_main
   1617       // should ensure this.
   1618       vg_assert(fnpatt && *fnpatt == sep);
   1619       *fnpatt = 0;
   1620       fnpatt++;
   1621       if (VG_(string_match)(sopatt, di_soname)) {
   1622          HChar *pattern = VG_(strdup)("m_redir.hrts.2", fnpatt);
   1623          VG_(addToXA)(fnpatts, &pattern);
   1624       }
   1625       VG_(free)(spec);
   1626    }
   1627 
   1628    if (VG_(sizeXA)(fnpatts) == 0) {
   1629       VG_(deleteXA)(fnpatts);
   1630       return;  /* no applicable spec strings */
   1631    }
   1632 
   1633    /* So finally, fnpatts contains the set of
   1634       (patterns for) text symbol names that must be found in this
   1635       object, in order to continue.  That is, we must find at least
   1636       one text symbol name that matches each pattern, else we must
   1637       abort the run. */
   1638 
   1639    if (0) VG_(printf)("for %s\n", di_soname);
   1640    for (i = 0; i < VG_(sizeXA)(fnpatts); i++)
   1641       if (0) VG_(printf)("   fnpatt: %s\n",
   1642                          *(HChar**) VG_(indexXA)(fnpatts, i));
   1643 
   1644    /* For each spec, look through the syms to find one that matches.
   1645       This isn't terribly efficient but it happens rarely, so no big
   1646       deal. */
   1647    for (i = 0; i < VG_(sizeXA)(fnpatts); i++) {
   1648       Bool   found  = False;
   1649       const HChar* fnpatt = *(HChar**) VG_(indexXA)(fnpatts, i);
   1650       Int    nsyms  = VG_(DebugInfo_syms_howmany)(di);
   1651       for (j = 0; j < nsyms; j++) {
   1652          Bool    isText        = False;
   1653          const HChar*  sym_name_pri  = NULL;
   1654          const HChar** sym_names_sec = NULL;
   1655          VG_(DebugInfo_syms_getidx)( di, j, NULL,
   1656                                      NULL, &sym_name_pri, &sym_names_sec,
   1657                                      &isText, NULL );
   1658          const HChar*  twoslots[2];
   1659          const HChar** names_init =
   1660             alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
   1661          const HChar** names;
   1662          for (names = names_init; *names; names++) {
   1663             /* ignore data symbols */
   1664             if (0) VG_(printf)("QQQ %s\n", *names);
   1665             vg_assert(sym_name_pri);
   1666             if (!isText)
   1667                continue;
   1668             if (VG_(string_match)(fnpatt, *names)) {
   1669                found = True;
   1670                break;
   1671             }
   1672          }
   1673          free_symname_array(names_init, &twoslots[0]);
   1674          if (found)
   1675             break;
   1676       }
   1677 
   1678       if (!found) {
   1679          const HChar* v = "valgrind:  ";
   1680          VG_(printf)("\n");
   1681          VG_(printf)(
   1682          "%sFatal error at when loading library with soname\n", v);
   1683          VG_(printf)(
   1684          "%s   %s\n", v, di_soname);
   1685          VG_(printf)(
   1686          "%sCannot find any text symbol with a name "
   1687          "that matches the pattern\n", v);
   1688          VG_(printf)("%s   %s\n", v, fnpatt);
   1689          VG_(printf)("%sas required by a --require-text-symbol= "
   1690          "specification.\n", v);
   1691          VG_(printf)("\n");
   1692          VG_(printf)(
   1693          "%sCannot continue -- exiting now.\n", v);
   1694          VG_(printf)("\n");
   1695          VG_(exit)(1);
   1696       }
   1697    }
   1698 
   1699    /* All required specs were found.  Just free memory and return. */
   1700    VG_(deleteXA)(fnpatts);
   1701 }
   1702 
   1703 
   1704 /*------------------------------------------------------------*/
   1705 /*--- SANITY/DEBUG                                         ---*/
   1706 /*------------------------------------------------------------*/
   1707 
   1708 static void show_spec ( const HChar* left, const Spec* spec )
   1709 {
   1710    VG_(message)( Vg_DebugMsg,
   1711                  "%s%-25s %-30s %s-> (%04d.%d) 0x%08lx\n",
   1712                  left,
   1713                  spec->from_sopatt, spec->from_fnpatt,
   1714                  spec->isWrap ? "W" : "R",
   1715                  spec->becTag, spec->becPrio,
   1716                  spec->to_addr );
   1717 }
   1718 
   1719 static void show_active ( const HChar* left, const Active* act )
   1720 {
   1721    Bool ok;
   1722    const HChar *buf;
   1723 
   1724    ok = VG_(get_fnname_w_offset)(act->from_addr, &buf);
   1725    if (!ok) buf = "???";
   1726    // Stash away name1
   1727    HChar name1[VG_(strlen)(buf) + 1];
   1728    VG_(strcpy)(name1, buf);
   1729 
   1730    const HChar *name2;
   1731    ok = VG_(get_fnname_w_offset)(act->to_addr, &name2);
   1732    if (!ok) name2 = "???";
   1733 
   1734    VG_(message)(Vg_DebugMsg, "%s0x%08lx (%-20s) %s-> (%04d.%d) 0x%08lx %s\n",
   1735                              left,
   1736                              act->from_addr, name1,
   1737                              act->isWrap ? "W" : "R",
   1738                              act->becTag, act->becPrio,
   1739                              act->to_addr, name2 );
   1740 }
   1741 
   1742 static void show_redir_state ( const HChar* who )
   1743 {
   1744    TopSpec* ts;
   1745    Spec*    sp;
   1746    Active*  act;
   1747    VG_(message)(Vg_DebugMsg, "<<\n");
   1748    VG_(message)(Vg_DebugMsg, "   ------ REDIR STATE %s ------\n", who);
   1749    for (ts = topSpecs; ts; ts = ts->next) {
   1750       if (ts->seginfo)
   1751          VG_(message)(Vg_DebugMsg,
   1752                       "   TOPSPECS of soname %s filename %s\n",
   1753                       VG_(DebugInfo_get_soname)(ts->seginfo),
   1754                       VG_(DebugInfo_get_filename)(ts->seginfo));
   1755       else
   1756          VG_(message)(Vg_DebugMsg,
   1757                       "   TOPSPECS of soname (hardwired)\n");
   1758 
   1759       for (sp = ts->specs; sp; sp = sp->next)
   1760          show_spec("     ", sp);
   1761    }
   1762    VG_(message)(Vg_DebugMsg, "   ------ ACTIVE ------\n");
   1763    VG_(OSetGen_ResetIter)( activeSet );
   1764    while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
   1765       show_active("    ", act);
   1766    }
   1767 
   1768    VG_(message)(Vg_DebugMsg, ">>\n");
   1769 }
   1770 
   1771 /*--------------------------------------------------------------------*/
   1772 /*--- end                                                          ---*/
   1773 /*--------------------------------------------------------------------*/
   1774