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-2017 Julian Seward
     11       jseward (at) acm.org
     12    Copyright (C) 2003-2017 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_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       Bool   isGlobal;     /* must the symbol to replace be global? */
    237       Int    becTag; /* 0 through 9999.  Behavioural equivalance class tag.
    238                         If two wrappers have the same (non-zero) tag, they
    239                         are promising that they behave identically. */
    240       Int    becPrio; /* 0 through 9.  Behavioural equivalence class prio.
    241                          Used to choose between competing wrappers with
    242                          the same (non-zero) tag. */
    243       const HChar** mandatory; /* non-NULL ==> abort V and print the
    244                                   strings if from_sopatt is loaded but
    245                                   from_fnpatt cannot be found */
    246       /* VARIABLE PARTS -- used transiently whilst processing redirections */
    247       Bool   mark; /* set if spec requires further processing */
    248       Bool   done; /* set if spec was successfully matched */
    249    }
    250    Spec;
    251 
    252 /* Top-level data structure.  It contains a pointer to a DebugInfo and
    253    also a list of the specs harvested from that DebugInfo.  Note that
    254    seginfo is allowed to be NULL, meaning that the specs are
    255    pre-loaded ones at startup and are not associated with any
    256    particular seginfo. */
    257 typedef
    258    struct _TopSpec {
    259       struct _TopSpec* next; /* linked list */
    260       const DebugInfo* seginfo;    /* symbols etc */
    261       Spec*      specs;      /* specs pulled out of seginfo */
    262       Bool       mark; /* transient temporary used during deletion */
    263    }
    264    TopSpec;
    265 
    266 /* This is the top level list of redirections.  m_debuginfo maintains
    267    a list of DebugInfos, and the idea here is to maintain a list with
    268    the same number of elements (in fact, with one more element, so as
    269    to record abovementioned preloaded specifications.) */
    270 static TopSpec* topSpecs = NULL;
    271 
    272 
    273 /*------------------------------------------------------------*/
    274 /*--- CURRENTLY ACTIVE REDIRECTIONS                        ---*/
    275 /*------------------------------------------------------------*/
    276 
    277 /* Represents a currently active binding.  If either parent_spec or
    278    parent_sym is NULL, then this binding was hardwired at startup and
    279    should not be deleted.  Same is true if either parent's seginfo
    280    field is NULL. */
    281 typedef
    282    struct {
    283       Addr     from_addr;   /* old addr -- MUST BE THE FIRST WORD! */
    284       Addr     to_addr;     /* where redirecting to */
    285       TopSpec* parent_spec; /* the TopSpec which supplied the Spec */
    286       TopSpec* parent_sym;  /* the TopSpec which supplied the symbol */
    287       Int      becTag;      /* behavioural eclass tag for ::to_addr */
    288       Int      becPrio;     /* and its priority */
    289       Bool     isWrap;      /* wrap or replacement? */
    290       Bool     isIFunc;     /* indirect function? */
    291    }
    292    Active;
    293 
    294 /* The active set is a fast lookup table */
    295 static OSet* activeSet = NULL;
    296 
    297 /* Wrapper routine for indirect functions */
    298 static Addr iFuncWrapper;
    299 
    300 /*------------------------------------------------------------*/
    301 /*--- FWDses                                               ---*/
    302 /*------------------------------------------------------------*/
    303 
    304 static void maybe_add_active ( Active /*by value; callee copies*/ );
    305 
    306 static void*  dinfo_zalloc(const HChar* ec, SizeT);
    307 static void   dinfo_free(void*);
    308 static HChar* dinfo_strdup(const HChar* ec, const HChar*);
    309 static Bool   is_plausible_guest_addr(Addr);
    310 
    311 static void   show_redir_state ( const HChar* who );
    312 static void   show_active ( const HChar* left, const Active* act );
    313 
    314 static void   handle_maybe_load_notifier( const HChar* soname,
    315                                           const HChar* symbol, Addr addr );
    316 
    317 static void   handle_require_text_symbols ( const DebugInfo* );
    318 
    319 /*------------------------------------------------------------*/
    320 /*--- NOTIFICATIONS                                        ---*/
    321 /*------------------------------------------------------------*/
    322 
    323 static
    324 void generate_and_add_actives (
    325         /* spec list and the owning TopSpec */
    326         Spec*    specs,
    327         TopSpec* parent_spec,
    328 	/* debuginfo and the owning TopSpec */
    329         const DebugInfo* di,
    330         TopSpec* parent_sym
    331      );
    332 
    333 
    334 /* Copy all the names from a given symbol into an AR_DINFO allocated,
    335    NULL terminated array, for easy iteration.  Caller must pass also
    336    the address of a 2-entry array which can be used in the common case
    337    to avoid dynamic allocation. */
    338 static const HChar** alloc_symname_array ( const HChar* pri_name,
    339                                            const HChar** sec_names,
    340                                            const HChar** twoslots )
    341 {
    342    /* Special-case the common case: only one name.  We expect the
    343       caller to supply a stack-allocated 2-entry array for this. */
    344    if (sec_names == NULL) {
    345       twoslots[0] = pri_name;
    346       twoslots[1] = NULL;
    347       return twoslots;
    348    }
    349    /* Else must use dynamic allocation.  Figure out size .. */
    350    Word    n_req = 1;
    351    const HChar** pp = sec_names;
    352    while (*pp) { n_req++; pp++; }
    353    /* .. allocate and copy in. */
    354    const HChar** arr = dinfo_zalloc("redir.asa.1", (n_req+1) * sizeof(HChar*));
    355    Word    i   = 0;
    356    arr[i++] = pri_name;
    357    pp = sec_names;
    358    while (*pp) { arr[i++] = *pp; pp++; }
    359    vg_assert(i == n_req);
    360    vg_assert(arr[n_req] == NULL);
    361    return arr;
    362 }
    363 
    364 
    365 /* Free the array allocated by alloc_symname_array, if any. */
    366 static void free_symname_array ( const HChar** names, const HChar** twoslots )
    367 {
    368    if (names != twoslots)
    369       dinfo_free(names);
    370 }
    371 
    372 static HChar const* advance_to_equal ( HChar const* c ) {
    373    while (*c && *c != '=') {
    374       ++c;
    375    }
    376    return c;
    377 }
    378 static HChar const* advance_to_comma ( HChar const* c ) {
    379    while (*c && *c != ',') {
    380       ++c;
    381    }
    382    return c;
    383 }
    384 
    385 /* Notify m_redir of the arrival of a new DebugInfo.  This is fairly
    386    complex, but the net effect is to (1) add a new entry to the
    387    topspecs list, and (2) figure out what new binding are now active,
    388    and, as a result, add them to the actives mapping. */
    389 
    390 void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi )
    391 {
    392    Bool         ok, isWrap, isGlobal;
    393    Int          i, nsyms, becTag, becPrio;
    394    Spec*        specList;
    395    Spec*        spec;
    396    TopSpec*     ts;
    397    TopSpec*     newts;
    398    const HChar*  sym_name_pri;
    399    const HChar** sym_names_sec;
    400    SymAVMAs     sym_avmas;
    401    const HChar* demangled_sopatt;
    402    const HChar* demangled_fnpatt;
    403    Bool         check_ppcTOCs = False;
    404    Bool         isText;
    405    const HChar* newdi_soname;
    406    Bool         dehacktivate_pthread_stack_cache_var_search = False;
    407    const HChar* const pthread_soname = "libpthread.so.0";
    408    const HChar* const pthread_stack_cache_actsize_varname
    409       = "stack_cache_actsize";
    410 #if defined(VGO_solaris)
    411    Bool         vg_vfork_fildes_var_search = False;
    412    const HChar* const vg_preload_core_soname = "vgpreload_core.so.0";
    413    const HChar* const vg_vfork_fildes_varname = "vg_vfork_fildes";
    414 #endif
    415 
    416 #  if defined(VG_PLAT_USES_PPCTOC)
    417    check_ppcTOCs = True;
    418 #  endif
    419 
    420    vg_assert(newdi);
    421    newdi_soname = VG_(DebugInfo_get_soname)(newdi);
    422    vg_assert(newdi_soname != NULL);
    423 
    424 #ifdef ENABLE_INNER
    425    {
    426       /* When an outer Valgrind is executing an inner Valgrind, the
    427          inner "sees" in its address space the mmap-ed vgpreload files
    428          of the outer.  The inner must avoid interpreting the
    429          redirections given in the outer vgpreload mmap-ed files.
    430          Otherwise, some tool combinations badly fail.
    431 
    432          Example: outer memcheck tool executing an inner none tool.
    433 
    434          If inner none interprets the outer malloc redirection, the
    435          inner will redirect malloc to a memcheck function it does not
    436          have (as the redirection target is from the outer).  With
    437          such a failed redirection, a call to malloc inside the inner
    438          will then result in a "no-operation" (and so no memory will
    439          be allocated).
    440 
    441          When running as an inner, no redirection will be done
    442          for a vgpreload file if this file is not located in the
    443          inner VALGRIND_LIB directory.
    444 
    445          Recognising a vgpreload file based on a filename pattern
    446          is a kludge. An alternate solution would be to change
    447          the _vgr prefix according to outer/inner/client.
    448       */
    449       const HChar* newdi_filename = VG_(DebugInfo_get_filename)(newdi);
    450       const HChar* newdi_basename = VG_(basename) (newdi_filename);
    451       if (VG_(strncmp) (newdi_basename, "vgpreload_", 10) == 0) {
    452          /* This looks like a vgpreload file => check if this file
    453             is from the inner VALGRIND_LIB.
    454             We do this check using VG_(stat) + dev/inode comparison
    455             as vg-in-place defines a VALGRIND_LIB with symlinks
    456             pointing to files inside the valgrind build directories. */
    457          struct vg_stat newdi_stat;
    458          SysRes newdi_res;
    459          struct vg_stat in_vglib_stat;
    460          SysRes in_vglib_res;
    461 
    462          newdi_res = VG_(stat)(newdi_filename, &newdi_stat);
    463 
    464          HChar in_vglib_filename[VG_(strlen)(VG_(libdir)) + 1 +
    465                                  VG_(strlen)(newdi_basename) + 1];
    466          VG_(sprintf)(in_vglib_filename, "%s/%s", VG_(libdir), newdi_basename);
    467 
    468          in_vglib_res = VG_(stat)(in_vglib_filename, &in_vglib_stat);
    469 
    470          /* If we find newdi_basename in inner VALGRIND_LIB
    471             but newdi_filename is not the same file, then we do
    472             not execute the redirection. */
    473          if (!sr_isError(in_vglib_res)
    474              && !sr_isError(newdi_res)
    475              && (newdi_stat.dev != in_vglib_stat.dev
    476                  || newdi_stat.ino != in_vglib_stat.ino)) {
    477             /* <inner VALGRIND_LIB>/newdi_basename is an existing file
    478                and is different of newdi_filename.
    479                So, we do not execute newdi_filename redirection. */
    480             if ( VG_(clo_verbosity) > 1 ) {
    481                VG_(message)( Vg_DebugMsg,
    482                              "Skipping vgpreload redir in %s"
    483                              " (not from VALGRIND_LIB_INNER)\n",
    484                              newdi_filename);
    485             }
    486             return;
    487          } else {
    488             if ( VG_(clo_verbosity) > 1 ) {
    489                VG_(message)( Vg_DebugMsg,
    490                              "Executing vgpreload redir in %s"
    491                              " (from VALGRIND_LIB_INNER)\n",
    492                              newdi_filename);
    493             }
    494          }
    495       }
    496    }
    497 #endif
    498 
    499 
    500    /* stay sane: we don't already have this. */
    501    for (ts = topSpecs; ts; ts = ts->next)
    502       vg_assert(ts->seginfo != newdi);
    503 
    504    /* scan this DebugInfo's symbol table, pulling out and demangling
    505       any specs found */
    506 
    507    specList = NULL; /* the spec list we're building up */
    508 
    509    dehacktivate_pthread_stack_cache_var_search =
    510       SimHintiS(SimHint_no_nptl_pthread_stackcache, VG_(clo_sim_hints))
    511       && 0 == VG_(strcmp)(newdi_soname, pthread_soname);
    512 
    513 #if defined(VGO_solaris)
    514    vg_vfork_fildes_var_search =
    515       0 == VG_(strcmp)(newdi_soname, vg_preload_core_soname);
    516 #endif
    517 
    518    nsyms = VG_(DebugInfo_syms_howmany)( newdi );
    519    for (i = 0; i < nsyms; i++) {
    520       VG_(DebugInfo_syms_getidx)( newdi, i, &sym_avmas,
    521                                   NULL, &sym_name_pri, &sym_names_sec,
    522                                   &isText, NULL, NULL );
    523       /* Set up to conveniently iterate over all names for this symbol. */
    524       const HChar*  twoslots[2];
    525       const HChar** names_init =
    526          alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
    527       const HChar** names;
    528       for (names = names_init; *names; names++) {
    529          isGlobal = False;
    530          ok = VG_(maybe_Z_demangle)( *names,
    531                                      &demangled_sopatt,
    532                                      &demangled_fnpatt,
    533                                      &isWrap, &becTag, &becPrio );
    534          /* ignore data symbols */
    535          if (!isText) {
    536             /* But search for dehacktivate stack cache var if needed. */
    537             if (dehacktivate_pthread_stack_cache_var_search
    538                 && 0 == VG_(strcmp)(*names,
    539                                     pthread_stack_cache_actsize_varname)) {
    540                if ( VG_(clo_verbosity) > 1 ) {
    541                   VG_(message)( Vg_DebugMsg,
    542                                 "deactivate nptl pthread stackcache via kludge:"
    543                                 " found symbol %s at addr %p\n",
    544                                 *names, (void*) sym_avmas.main);
    545                }
    546                VG_(client__stack_cache_actsize__addr) = (SizeT*) sym_avmas.main;
    547                dehacktivate_pthread_stack_cache_var_search = False;
    548             }
    549 #if defined(VGO_solaris)
    550             if (vg_vfork_fildes_var_search
    551                 && 0 == VG_(strcmp)(*names, vg_vfork_fildes_varname)) {
    552                if ( VG_(clo_verbosity) > 1 ) {
    553                   VG_(message)( Vg_DebugMsg,
    554                                 "vfork kludge: found symbol %s at addr %p\n",
    555                                 *names, (void*) sym_avmas.main);
    556                }
    557                VG_(vfork_fildes_addr) = (Int*) sym_avmas.main;
    558                vg_vfork_fildes_var_search = False;
    559             }
    560 #endif
    561             continue;
    562          }
    563          if (!ok) {
    564             /* It's not a full-scale redirect, but perhaps it is a load-notify
    565                fn?  Let the load-notify department see it. */
    566             handle_maybe_load_notifier( newdi_soname, *names, sym_avmas.main );
    567             continue;
    568          }
    569          if (check_ppcTOCs && GET_TOCPTR_AVMA(sym_avmas) == 0) {
    570             /* This platform uses toc pointers, but none could be found
    571                for this symbol, so we can't safely redirect/wrap to it.
    572                Just skip it; we'll make a second pass over the symbols in
    573                the following loop, and complain at that point. */
    574             continue;
    575          }
    576 
    577          HChar *replaced_sopatt = NULL;
    578          if (0 == VG_(strncmp) (demangled_sopatt,
    579                                 VG_SO_SYN_PREFIX, VG_SO_SYN_PREFIX_LEN)) {
    580             /* This is a redirection for handling lib so synonyms. If we
    581                have a matching lib synonym, then replace the sopatt.
    582                Otherwise, just ignore this redirection spec. */
    583 
    584             /* Search for a matching synonym=newname*/
    585             SizeT const sopatt_syn_len
    586                = VG_(strlen)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN);
    587             HChar const* last = VG_(clo_soname_synonyms);
    588 
    589             while (last != NULL && *last) {
    590                HChar const* first = last;
    591                last = advance_to_equal(first);
    592 
    593                if ((last - first) == sopatt_syn_len
    594                    && 0 == VG_(strncmp)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN,
    595                                         first,
    596                                         sopatt_syn_len)) {
    597                   // Found the demangle_sopatt synonym => replace it
    598                   first = last + 1;
    599                   last = advance_to_comma(first);
    600                   replaced_sopatt = dinfo_zalloc("redir.rnnD.5",
    601                                                  last - first + 1);
    602                   VG_(strncpy)(replaced_sopatt, first, last - first);
    603                   replaced_sopatt[last - first] = '\0';
    604                   demangled_sopatt = replaced_sopatt;
    605                   break;
    606                }
    607 
    608                last = advance_to_comma(last);
    609                if (*last == ',')
    610                   last++;
    611             }
    612 
    613 	    // If the user didn't set it then somalloc is special. We
    614 	    // want to match public/global symbols that match the
    615 	    // fnpatt everywhere.
    616 	    if (replaced_sopatt == NULL
    617 		&& VG_(strcmp) ( demangled_sopatt, SO_SYN_MALLOC_NAME ) == 0)
    618 	      {
    619 		replaced_sopatt = dinfo_strdup("m_redir.rnnD.1", "*");
    620 		demangled_sopatt = replaced_sopatt;
    621 		isGlobal = True;
    622 	      }
    623 
    624             // If we have not replaced the sopatt, then skip the redir.
    625             if (replaced_sopatt == NULL)
    626                continue;
    627          }
    628 
    629          spec = dinfo_zalloc("redir.rnnD.1", sizeof(Spec));
    630          spec->from_sopatt = dinfo_strdup("redir.rnnD.2", demangled_sopatt);
    631          spec->from_fnpatt = dinfo_strdup("redir.rnnD.3", demangled_fnpatt);
    632          spec->to_addr = sym_avmas.main;
    633          spec->isWrap = isWrap;
    634          spec->isGlobal = isGlobal;
    635          spec->becTag = becTag;
    636          spec->becPrio = becPrio;
    637          /* check we're not adding manifestly stupid destinations */
    638          vg_assert(is_plausible_guest_addr(sym_avmas.main));
    639          spec->next = specList;
    640          spec->mark = False; /* not significant */
    641          spec->done = False; /* not significant */
    642          specList = spec;
    643          /* The demangler is the owner of the demangled_sopatt memory,
    644             unless it was replaced. In this case, we have to free the
    645             replace_sopatt(==demangled_sopatt).  We can free it,
    646             because it was dinfo_strup-ed into spec->from_sopatt. */
    647          if (replaced_sopatt != NULL) {
    648             vg_assert(demangled_sopatt == replaced_sopatt);
    649             dinfo_free(replaced_sopatt);
    650          }
    651       }
    652       free_symname_array(names_init, &twoslots[0]);
    653    }
    654    if (dehacktivate_pthread_stack_cache_var_search) {
    655       VG_(message)(Vg_DebugMsg,
    656                    "WARNING: could not find symbol for var %s in %s\n",
    657                    pthread_stack_cache_actsize_varname, pthread_soname);
    658       VG_(message)(Vg_DebugMsg,
    659                    "=> pthread stack cache cannot be disabled!\n");
    660    }
    661 #if defined(VGO_solaris)
    662    if (vg_vfork_fildes_var_search) {
    663       VG_(message)(Vg_DebugMsg,
    664                    "WARNING: could not find symbol for var %s in %s\n",
    665                    vg_vfork_fildes_varname, vg_preload_core_soname);
    666       VG_(message)(Vg_DebugMsg,
    667                    "=> posix_spawn() will not work correctly!\n");
    668    }
    669 #endif
    670 
    671    if (check_ppcTOCs) {
    672       for (i = 0; i < nsyms; i++) {
    673          VG_(DebugInfo_syms_getidx)( newdi, i, &sym_avmas,
    674                                      NULL, &sym_name_pri, &sym_names_sec,
    675                                      &isText, NULL, NULL );
    676          const HChar*  twoslots[2];
    677          const HChar** names_init =
    678             alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
    679          const HChar** names;
    680          for (names = names_init; *names; names++) {
    681             ok = isText
    682                  && VG_(maybe_Z_demangle)(
    683                        *names, &demangled_sopatt,
    684                        &demangled_fnpatt, &isWrap, NULL, NULL );
    685             if (!ok)
    686                /* not a redirect.  Ignore. */
    687                continue;
    688             if (GET_TOCPTR_AVMA(sym_avmas) != 0)
    689                /* has a valid toc pointer.  Ignore. */
    690                continue;
    691 
    692             for (spec = specList; spec; spec = spec->next)
    693                if (0 == VG_(strcmp)(spec->from_sopatt, demangled_sopatt)
    694                    && 0 == VG_(strcmp)(spec->from_fnpatt, demangled_fnpatt))
    695                   break;
    696             if (spec)
    697                /* a redirect to some other copy of that symbol, which
    698                   does have a TOC value, already exists */
    699                continue;
    700 
    701             /* Complain */
    702             VG_(message)(Vg_DebugMsg,
    703                          "WARNING: no TOC ptr for redir/wrap to %s %s\n",
    704                          demangled_sopatt, demangled_fnpatt);
    705          }
    706          free_symname_array(names_init, &twoslots[0]);
    707       }
    708    }
    709 
    710    /* Ok.  Now specList holds the list of specs from the DebugInfo.
    711       Build a new TopSpec, but don't add it to topSpecs yet. */
    712    newts = dinfo_zalloc("redir.rnnD.4", sizeof(TopSpec));
    713    newts->next    = NULL; /* not significant */
    714    newts->seginfo = newdi;
    715    newts->specs   = specList;
    716    newts->mark    = False; /* not significant */
    717 
    718    /* We now need to augment the active set with the following partial
    719       cross product:
    720 
    721       (1) actives formed by matching the new specs in specList against
    722           all symbols currently listed in topSpecs
    723 
    724       (2) actives formed by matching the new symbols in newdi against
    725           all specs currently listed in topSpecs
    726 
    727       (3) actives formed by matching the new symbols in newdi against
    728           the new specs in specList
    729 
    730       This is necessary in order to maintain the invariant that
    731       Actives contains all bindings generated by matching ALL specs in
    732       topSpecs against ALL symbols in topSpecs (that is, a cross
    733       product of ALL known specs against ALL known symbols).
    734    */
    735    /* Case (1) */
    736    for (ts = topSpecs; ts; ts = ts->next) {
    737       if (ts->seginfo)
    738          generate_and_add_actives( specList,    newts,
    739                                    ts->seginfo, ts );
    740    }
    741 
    742    /* Case (2) */
    743    for (ts = topSpecs; ts; ts = ts->next) {
    744       generate_and_add_actives( ts->specs, ts,
    745                                 newdi,     newts );
    746    }
    747 
    748    /* Case (3) */
    749    generate_and_add_actives( specList, newts,
    750                              newdi,    newts );
    751 
    752    /* Finally, add the new TopSpec. */
    753    newts->next = topSpecs;
    754    topSpecs = newts;
    755 
    756    if (VG_(clo_trace_redir))
    757       show_redir_state("after VG_(redir_notify_new_DebugInfo)");
    758 
    759    /* Really finally (quite unrelated to all the above) check the
    760       names in the module against any --require-text-symbol=
    761       specifications we might have. */
    762    handle_require_text_symbols(newdi);
    763 }
    764 
    765 /* Add a new target for an indirect function. Adds a new redirection
    766    for the indirection function with address old_from that redirects
    767    the ordinary function with address new_from to the target address
    768    of the original redirection. */
    769 
    770 void VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from )
    771 {
    772     Active *old, new;
    773 
    774     old = VG_(OSetGen_Lookup)(activeSet, &old_from);
    775     vg_assert(old);
    776     vg_assert(old->isIFunc);
    777 
    778     new = *old;
    779     new.from_addr = new_from;
    780     new.isIFunc = False;
    781     maybe_add_active (new);
    782 
    783     if (VG_(clo_trace_redir)) {
    784        VG_(message)( Vg_DebugMsg,
    785                      "Adding redirect for indirect function "
    786                      "0x%lx from 0x%lx -> 0x%lx\n",
    787                      old_from, new_from, new.to_addr );
    788     }
    789 }
    790 
    791 /* Do one element of the basic cross product: add to the active set,
    792    all matches resulting from comparing all the given specs against
    793    all the symbols in the given seginfo.  If a conflicting binding
    794    would thereby arise, don't add it, but do complain. */
    795 
    796 static
    797 void generate_and_add_actives (
    798         /* spec list and the owning TopSpec */
    799         Spec*    specs,
    800         TopSpec* parent_spec,
    801 	/* seginfo and the owning TopSpec */
    802         const DebugInfo* di,
    803         TopSpec* parent_sym
    804      )
    805 {
    806    Spec*   sp;
    807    Bool    anyMark, isText, isIFunc, isGlobal;
    808    Active  act;
    809    Int     nsyms, i;
    810    SymAVMAs  sym_avmas;
    811    const HChar*  sym_name_pri;
    812    const HChar** sym_names_sec;
    813 
    814    /* First figure out which of the specs match the seginfo's soname.
    815       Also clear the 'done' bits, so that after the main loop below
    816       tell which of the Specs really did get done. */
    817    anyMark = False;
    818    for (sp = specs; sp; sp = sp->next) {
    819       sp->done = False;
    820       const HChar *soname = VG_(DebugInfo_get_soname)(di);
    821 
    822       /* When searching for global public symbols (like for the somalloc
    823          synonym symbols), exclude the dynamic (runtime) linker as it is very
    824          special. See https://bugs.kde.org/show_bug.cgi?id=355454 */
    825       if ((VG_(strcmp)(sp->from_sopatt, "*") == 0) &&
    826           (sp->isGlobal == True) &&
    827           VG_(is_soname_ld_so)(soname)) {
    828          sp->mark = False;
    829          continue;
    830       }
    831 
    832       sp->mark = VG_(string_match)( sp->from_sopatt, soname );
    833       anyMark = anyMark || sp->mark;
    834    }
    835 
    836    /* shortcut: if none of the sonames match, there will be no bindings. */
    837    if (!anyMark)
    838       return;
    839 
    840    /* Iterate outermost over the symbols in the seginfo, in the hope
    841       of trashing the caches less. */
    842    nsyms = VG_(DebugInfo_syms_howmany)( di );
    843    for (i = 0; i < nsyms; i++) {
    844       VG_(DebugInfo_syms_getidx)( di, i, &sym_avmas,
    845                                   NULL, &sym_name_pri, &sym_names_sec,
    846                                   &isText, &isIFunc, &isGlobal );
    847       const HChar*  twoslots[2];
    848       const HChar** names_init =
    849          alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
    850       const HChar** names;
    851       for (names = names_init; *names; names++) {
    852 
    853          /* ignore data symbols */
    854          if (!isText)
    855             continue;
    856 
    857          for (sp = specs; sp; sp = sp->next) {
    858             if (!sp->mark)
    859                continue; /* soname doesn't match */
    860             if (VG_(string_match)( sp->from_fnpatt, *names )
    861 		&& (sp->isGlobal == False || isGlobal == True)) {
    862                /* got a new binding.  Add to collection. */
    863                act.from_addr   = sym_avmas.main;
    864                act.to_addr     = sp->to_addr;
    865                act.parent_spec = parent_spec;
    866                act.parent_sym  = parent_sym;
    867                act.becTag      = sp->becTag;
    868                act.becPrio     = sp->becPrio;
    869                act.isWrap      = sp->isWrap;
    870                act.isIFunc     = isIFunc;
    871                sp->done = True;
    872                maybe_add_active( act );
    873 
    874                /* If the function being wrapped has a local entry point
    875                 * redirect it to the global entry point.  The redirection
    876                 * must save and setup r2 then setup r12 for the new function.
    877                 * On return, r2 must be restored.  Local entry points used
    878                 * in PPC64 Little Endian.
    879                 */
    880                if (GET_LOCAL_EP_AVMA(sym_avmas) != 0) {
    881                   act.from_addr = GET_LOCAL_EP_AVMA(sym_avmas);
    882                   maybe_add_active( act );
    883                }
    884 
    885             }
    886          } /* for (sp = specs; sp; sp = sp->next) */
    887 
    888       } /* iterating over names[] */
    889       free_symname_array(names_init, &twoslots[0]);
    890    } /* for (i = 0; i < nsyms; i++)  */
    891 
    892    /* Now, finally, look for Specs which were marked to be done, but
    893       didn't get matched.  If any such are mandatory we must abort the
    894       system at this point. */
    895    for (sp = specs; sp; sp = sp->next) {
    896       if (!sp->mark)
    897          continue;
    898       if (sp->mark && (!sp->done) && sp->mandatory)
    899          break;
    900    }
    901    if (sp) {
    902       const HChar** strp;
    903       const HChar* v = "valgrind:  ";
    904       vg_assert(sp->mark);
    905       vg_assert(!sp->done);
    906       vg_assert(sp->mandatory);
    907       VG_(printf)("\n");
    908       VG_(printf)(
    909       "%sFatal error at startup: a function redirection\n", v);
    910       VG_(printf)(
    911       "%swhich is mandatory for this platform-tool combination\n", v);
    912       VG_(printf)(
    913       "%scannot be set up.  Details of the redirection are:\n", v);
    914       VG_(printf)(
    915       "%s\n", v);
    916       VG_(printf)(
    917       "%sA must-be-redirected function\n", v);
    918       VG_(printf)(
    919       "%swhose name matches the pattern:      %s\n", v, sp->from_fnpatt);
    920       VG_(printf)(
    921       "%sin an object with soname matching:   %s\n", v, sp->from_sopatt);
    922       VG_(printf)(
    923       "%swas not found whilst processing\n", v);
    924       VG_(printf)(
    925       "%ssymbols from the object with soname: %s\n",
    926       v, VG_(DebugInfo_get_soname)(di));
    927       VG_(printf)(
    928       "%s\n", v);
    929 
    930       for (strp = sp->mandatory; *strp; strp++)
    931          VG_(printf)(
    932          "%s%s\n", v, *strp);
    933 
    934       VG_(printf)(
    935       "%s\n", v);
    936       VG_(printf)(
    937       "%sCannot continue -- exiting now.  Sorry.\n", v);
    938       VG_(printf)("\n");
    939       VG_(exit)(1);
    940    }
    941 }
    942 
    943 
    944 /* Add an act (passed by value; is copied here) and deal with
    945    conflicting bindings. */
    946 static void maybe_add_active ( Active act )
    947 {
    948    const HChar*  what = NULL;
    949    Active* old     = NULL;
    950    Bool    add_act = False;
    951 
    952    /* Complain and ignore manifestly bogus 'from' addresses.
    953 
    954       Kludge: because this can get called befor the trampoline area (a
    955       bunch of magic 'to' addresses) has its ownership changed from V
    956       to C, we can't check the 'to' address similarly.  Sigh.
    957 
    958       amd64-linux hack: the vsysinfo pages appear to have no
    959       permissions
    960          ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0
    961       so skip the check for them.  */
    962    if (!is_plausible_guest_addr(act.from_addr)
    963 #      if defined(VGP_amd64_linux)
    964        && act.from_addr != 0xFFFFFFFFFF600000ULL
    965        && act.from_addr != 0xFFFFFFFFFF600400ULL
    966        && act.from_addr != 0xFFFFFFFFFF600800ULL
    967 #      endif
    968       ) {
    969       what = "redirection from-address is in non-executable area";
    970       goto bad;
    971    }
    972 
    973    old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr );
    974    if (old) {
    975       /* Dodgy.  Conflicting binding. */
    976       vg_assert(old->from_addr == act.from_addr);
    977       if (old->to_addr != act.to_addr) {
    978          /* We've got a conflicting binding -- that is, from_addr is
    979             specified to redirect to two different destinations,
    980             old->to_addr and act.to_addr.  If we can prove that they
    981             are behaviourally equivalent then that's no problem.  So
    982             we can look at the behavioural eclass tags for both
    983             functions to see if that's so.  If they are equal, and
    984             nonzero, then that's fine.  But if not, we can't show they
    985             are equivalent, so we have to complain, and ignore the new
    986             binding. */
    987          vg_assert(old->becTag  >= 0 && old->becTag  <= 9999);
    988          vg_assert(old->becPrio >= 0 && old->becPrio <= 9);
    989          vg_assert(act.becTag   >= 0 && act.becTag   <= 9999);
    990          vg_assert(act.becPrio  >= 0 && act.becPrio  <= 9);
    991          if (old->becTag == 0)
    992             vg_assert(old->becPrio == 0);
    993          if (act.becTag == 0)
    994             vg_assert(act.becPrio == 0);
    995 
    996          if (old->becTag == 0 || act.becTag == 0 || old->becTag != act.becTag) {
    997             /* We can't show that they are equivalent.  Complain and
    998                ignore. */
    999             what = "new redirection conflicts with existing -- ignoring it";
   1000             goto bad;
   1001          }
   1002          /* They have the same eclass tag.  Use the priorities to
   1003             resolve the ambiguity. */
   1004          if (act.becPrio <= old->becPrio) {
   1005             /* The new one doesn't have a higher priority, so just
   1006                ignore it. */
   1007             if (VG_(clo_verbosity) > 2) {
   1008                VG_(message)(Vg_UserMsg, "Ignoring %s redirection:\n",
   1009                             act.becPrio < old->becPrio ? "lower priority"
   1010                                                        : "duplicate");
   1011                show_active(             "    old: ", old);
   1012                show_active(             "    new: ", &act);
   1013             }
   1014          } else {
   1015             /* The tricky case.  The new one has a higher priority, so
   1016                we need to get the old one out of the OSet and install
   1017                this one in its place. */
   1018             if (VG_(clo_verbosity) > 1) {
   1019                VG_(message)(Vg_UserMsg,
   1020                            "Preferring higher priority redirection:\n");
   1021                show_active(             "    old: ", old);
   1022                show_active(             "    new: ", &act);
   1023             }
   1024             add_act = True;
   1025             void* oldNd = VG_(OSetGen_Remove)( activeSet, &act.from_addr );
   1026             vg_assert(oldNd == old);
   1027             VG_(OSetGen_FreeNode)( activeSet, old );
   1028             old = NULL;
   1029          }
   1030       } else {
   1031          /* This appears to be a duplicate of an existing binding.
   1032             Safe(ish) -- ignore. */
   1033          /* XXXXXXXXXXX COMPLAIN if new and old parents differ */
   1034       }
   1035 
   1036    } else {
   1037       /* There's no previous binding for this from_addr, so we must
   1038          add 'act' to the active set. */
   1039       add_act = True;
   1040    }
   1041 
   1042    /* So, finally, actually add it. */
   1043    if (add_act) {
   1044       Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
   1045       vg_assert(a);
   1046       *a = act;
   1047       VG_(OSetGen_Insert)(activeSet, a);
   1048       /* Now that a new from->to redirection is in force, we need to
   1049          get rid of any translations intersecting 'from' in order that
   1050          they get redirected to 'to'.  So discard them.  Just for
   1051          paranoia (but, I believe, unnecessarily), discard 'to' as
   1052          well. */
   1053       VG_(discard_translations)( act.from_addr, 1,
   1054                                  "redir_new_DebugInfo(from_addr)");
   1055       VG_(discard_translations)( act.to_addr, 1,
   1056                                  "redir_new_DebugInfo(to_addr)");
   1057       if (VG_(clo_verbosity) > 2) {
   1058          VG_(message)(Vg_UserMsg, "Adding active redirection:\n");
   1059          show_active(             "    new: ", &act);
   1060       }
   1061    }
   1062    return;
   1063 
   1064   bad:
   1065    vg_assert(what);
   1066    vg_assert(!add_act);
   1067    if (VG_(clo_verbosity) > 1) {
   1068       VG_(message)(Vg_UserMsg, "WARNING: %s\n", what);
   1069       if (old) {
   1070          show_active(             "    old: ", old);
   1071       }
   1072       show_active(             "    new: ", &act);
   1073    }
   1074 }
   1075 
   1076 
   1077 /* Notify m_redir of the deletion of a DebugInfo.  This is relatively
   1078    simple -- just get rid of all actives derived from it, and free up
   1079    the associated list elements. */
   1080 
   1081 void VG_(redir_notify_delete_DebugInfo)( const DebugInfo* delsi )
   1082 {
   1083    TopSpec* ts;
   1084    TopSpec* tsPrev;
   1085    Spec*    sp;
   1086    Spec*    sp_next;
   1087    OSet*    tmpSet;
   1088    Active*  act;
   1089    Bool     delMe;
   1090    Addr     addr;
   1091 
   1092    vg_assert(delsi);
   1093 
   1094    /* Search for it, and make tsPrev point to the previous entry, if
   1095       any. */
   1096    tsPrev = NULL;
   1097    ts     = topSpecs;
   1098    while (True) {
   1099      if (ts == NULL) break;
   1100      if (ts->seginfo == delsi) break;
   1101      tsPrev = ts;
   1102      ts = ts->next;
   1103    }
   1104 
   1105    vg_assert(ts); /* else we don't have the deleted DebugInfo */
   1106    vg_assert(ts->seginfo == delsi);
   1107 
   1108    /* Traverse the actives, copying the addresses of those we intend
   1109       to delete into tmpSet. */
   1110    tmpSet = VG_(OSetWord_Create)(dinfo_zalloc, "redir.rndD.1", dinfo_free);
   1111 
   1112    ts->mark = True;
   1113 
   1114    VG_(OSetGen_ResetIter)( activeSet );
   1115    while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
   1116       delMe = act->parent_spec != NULL
   1117               && act->parent_sym != NULL
   1118               && act->parent_spec->seginfo != NULL
   1119               && act->parent_sym->seginfo != NULL
   1120               && (act->parent_spec->mark || act->parent_sym->mark);
   1121 
   1122       /* While we're at it, a bit of paranoia: delete any actives
   1123          which don't have both feet in valid client executable areas.
   1124          But don't delete hardwired-at-startup ones; these are denoted
   1125          by having parent_spec or parent_sym being NULL.  */
   1126       if ( (!delMe)
   1127            && act->parent_spec != NULL
   1128            && act->parent_sym  != NULL ) {
   1129          if (!is_plausible_guest_addr(act->from_addr))
   1130             delMe = True;
   1131          if (!is_plausible_guest_addr(act->to_addr))
   1132             delMe = True;
   1133       }
   1134 
   1135       if (delMe) {
   1136          VG_(OSetWord_Insert)( tmpSet, act->from_addr );
   1137          /* While we have our hands on both the 'from' and 'to'
   1138             of this Active, do paranoid stuff with tt/tc. */
   1139          VG_(discard_translations)( act->from_addr, 1,
   1140                                     "redir_del_DebugInfo(from_addr)");
   1141          VG_(discard_translations)( act->to_addr, 1,
   1142                                     "redir_del_DebugInfo(to_addr)");
   1143       }
   1144    }
   1145 
   1146    /* Now traverse tmpSet, deleting corresponding elements in activeSet. */
   1147    VG_(OSetWord_ResetIter)( tmpSet );
   1148    while ( VG_(OSetWord_Next)(tmpSet, &addr) ) {
   1149       act = VG_(OSetGen_Remove)( activeSet, &addr );
   1150       vg_assert(act);
   1151       VG_(OSetGen_FreeNode)( activeSet, act );
   1152    }
   1153 
   1154    VG_(OSetWord_Destroy)( tmpSet );
   1155 
   1156    /* The Actives set is now cleaned up.  Free up this TopSpec and
   1157       everything hanging off it. */
   1158    for (sp = ts->specs; sp; sp = sp_next) {
   1159       if (sp->from_sopatt) dinfo_free(sp->from_sopatt);
   1160       if (sp->from_fnpatt) dinfo_free(sp->from_fnpatt);
   1161       sp_next = sp->next;
   1162       dinfo_free(sp);
   1163    }
   1164 
   1165    if (tsPrev == NULL) {
   1166       /* first in list */
   1167       topSpecs = ts->next;
   1168    } else {
   1169       tsPrev->next = ts->next;
   1170    }
   1171    dinfo_free(ts);
   1172 
   1173    if (VG_(clo_trace_redir))
   1174       show_redir_state("after VG_(redir_notify_delete_DebugInfo)");
   1175 }
   1176 
   1177 
   1178 /*------------------------------------------------------------*/
   1179 /*--- QUERIES (really the whole point of this module)      ---*/
   1180 /*------------------------------------------------------------*/
   1181 
   1182 /* This is the crucial redirection function.  It answers the question:
   1183    should this code address be redirected somewhere else?  It's used
   1184    just before translating a basic block. */
   1185 Addr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap )
   1186 {
   1187    Active* r = VG_(OSetGen_Lookup)(activeSet, &orig);
   1188    if (r == NULL)
   1189       return orig;
   1190 
   1191    vg_assert(r->to_addr != 0);
   1192    if (isWrap)
   1193       *isWrap = r->isWrap || r->isIFunc;
   1194    if (r->isIFunc) {
   1195       vg_assert(iFuncWrapper);
   1196       return iFuncWrapper;
   1197    }
   1198    return r->to_addr;
   1199 }
   1200 
   1201 /* Does the soname represent a dynamic (runtime) linker?
   1202    Considers various VG_U_LD* entries from pub_tool_redir.h. */
   1203 Bool VG_(is_soname_ld_so) (const HChar *soname)
   1204 {
   1205 #  if defined(VGO_linux)
   1206    if (VG_STREQ(soname, VG_U_LD_LINUX_SO_3))         return True;
   1207    if (VG_STREQ(soname, VG_U_LD_LINUX_SO_2))         return True;
   1208    if (VG_STREQ(soname, VG_U_LD_LINUX_X86_64_SO_2))  return True;
   1209    if (VG_STREQ(soname, VG_U_LD64_SO_1))             return True;
   1210    if (VG_STREQ(soname, VG_U_LD64_SO_2))             return True;
   1211    if (VG_STREQ(soname, VG_U_LD_SO_1))               return True;
   1212    if (VG_STREQ(soname, VG_U_LD_LINUX_AARCH64_SO_1)) return True;
   1213    if (VG_STREQ(soname, VG_U_LD_LINUX_ARMHF_SO_3))   return True;
   1214 #  elif defined(VGO_darwin)
   1215    if (VG_STREQ(soname, VG_U_DYLD)) return True;
   1216 #  elif defined(VGO_solaris)
   1217    if (VG_STREQ(soname, VG_U_LD_SO_1)) return True;
   1218 #  else
   1219 #    error "Unsupported OS"
   1220 #  endif
   1221 
   1222    return False;
   1223 }
   1224 
   1225 /*------------------------------------------------------------*/
   1226 /*--- INITIALISATION                                       ---*/
   1227 /*------------------------------------------------------------*/
   1228 
   1229 /* Add a never-delete-me Active. */
   1230 
   1231 __attribute__((unused)) /* only used on amd64 */
   1232 static void add_hardwired_active ( Addr from, Addr to )
   1233 {
   1234    Active act;
   1235    act.from_addr   = from;
   1236    act.to_addr     = to;
   1237    act.parent_spec = NULL;
   1238    act.parent_sym  = NULL;
   1239    act.becTag      = 0; /* "not equivalent to any other fn" */
   1240    act.becPrio     = 0; /* mandatory when becTag == 0 */
   1241    act.isWrap      = False;
   1242    act.isIFunc     = False;
   1243    maybe_add_active( act );
   1244 }
   1245 
   1246 
   1247 /* Add a never-delete-me Spec.  This is a bit of a kludge.  On the
   1248    assumption that this is called only at startup, only handle the
   1249    case where topSpecs is completely empty, or if it isn't, it has
   1250    just one entry and that is the one with NULL seginfo -- that is the
   1251    entry that holds these initial specs. */
   1252 
   1253 __attribute__((unused)) /* not used on all platforms */
   1254 static void add_hardwired_spec (const  HChar* sopatt, const HChar* fnpatt,
   1255                                 Addr   to_addr,
   1256                                 const HChar** mandatory )
   1257 {
   1258    Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec));
   1259 
   1260    if (topSpecs == NULL) {
   1261       topSpecs = dinfo_zalloc("redir.ahs.2", sizeof(TopSpec));
   1262       /* symtab_zalloc sets all fields to zero */
   1263    }
   1264 
   1265    vg_assert(topSpecs != NULL);
   1266    vg_assert(topSpecs->next == NULL);
   1267    vg_assert(topSpecs->seginfo == NULL);
   1268    /* FIXED PARTS */
   1269    /* Note, that these CONST_CAST will not cause a problem, in the sense
   1270       that VG_(redir_notify_delete_DebugInfo) will delete them. The reason
   1271       is that the TopSpec here has seginfo == NULL and such a TopSpec will
   1272       never be freed. See the asserts at the beginning of said function. */
   1273    spec->from_sopatt = CONST_CAST(HChar *,sopatt);
   1274    spec->from_fnpatt = CONST_CAST(HChar *,fnpatt);
   1275    spec->to_addr     = to_addr;
   1276    spec->isWrap      = False;
   1277    spec->isGlobal    = False;
   1278    spec->mandatory   = mandatory;
   1279    /* VARIABLE PARTS */
   1280    spec->mark        = False; /* not significant */
   1281    spec->done        = False; /* not significant */
   1282 
   1283    spec->next = topSpecs->specs;
   1284    topSpecs->specs = spec;
   1285 }
   1286 
   1287 
   1288 __attribute__((unused)) /* not used on all platforms */
   1289 static const HChar* complain_about_stripped_glibc_ldso[]
   1290 = { "Possible fixes: (1, short term): install glibc's debuginfo",
   1291     "package on this machine.  (2, longer term): ask the packagers",
   1292     "for your Linux distribution to please in future ship a non-",
   1293     "stripped ld.so (or whatever the dynamic linker .so is called)",
   1294     "that exports the above-named function using the standard",
   1295     "calling conventions for this platform.  The package you need",
   1296     "to install for fix (1) is called",
   1297     "",
   1298     "  On Debian, Ubuntu:                 libc6-dbg",
   1299     "  On SuSE, openSuSE, Fedora, RHEL:   glibc-debuginfo",
   1300     "",
   1301     "Note that if you are debugging a 32 bit process on a",
   1302     "64 bit system, you will need a corresponding 32 bit debuginfo",
   1303     "package (e.g. libc6-dbg:i386).",
   1304     NULL
   1305   };
   1306 
   1307 
   1308 /* Initialise the redir system, and create the initial Spec list and
   1309    for amd64-linux a couple of permanent active mappings.  The initial
   1310    Specs are not converted into Actives yet, on the (checked)
   1311    assumption that no DebugInfos have so far been created, and so when
   1312    they are created, that will happen. */
   1313 
   1314 void VG_(redir_initialise) ( void )
   1315 {
   1316    // Assert that there are no DebugInfos so far
   1317    vg_assert( VG_(next_DebugInfo)(NULL) == NULL );
   1318 
   1319    // Initialise active mapping.
   1320    activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr),
   1321                                    NULL,     // Use fast comparison
   1322                                    dinfo_zalloc,
   1323                                    "redir.ri.1",
   1324                                    dinfo_free);
   1325 
   1326    // The rest of this function just adds initial Specs.
   1327 
   1328 #  if defined(VGP_x86_linux)
   1329    /* If we're using memcheck, use this intercept right from the
   1330       start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */
   1331    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1332       const HChar** mandatory;
   1333 #     ifndef GLIBC_MANDATORY_INDEX_AND_STRLEN_REDIRECT
   1334       mandatory = NULL;
   1335 #     else
   1336       /* for glibc-2.12 and later, this is mandatory - can't sanely
   1337          continue without it */
   1338       mandatory = complain_about_stripped_glibc_ldso;
   1339 #     endif
   1340       add_hardwired_spec(
   1341          "ld-linux.so.2", "index",
   1342          (Addr)&VG_(x86_linux_REDIR_FOR_index), mandatory);
   1343       add_hardwired_spec(
   1344          "ld-linux.so.2", "strlen",
   1345          (Addr)&VG_(x86_linux_REDIR_FOR_strlen), mandatory);
   1346    }
   1347 
   1348 #  elif defined(VGP_amd64_linux)
   1349    /* Redirect vsyscalls to local versions */
   1350    add_hardwired_active(
   1351       0xFFFFFFFFFF600000ULL,
   1352       (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday)
   1353    );
   1354    add_hardwired_active(
   1355       0xFFFFFFFFFF600400ULL,
   1356       (Addr)&VG_(amd64_linux_REDIR_FOR_vtime)
   1357    );
   1358    add_hardwired_active(
   1359       0xFFFFFFFFFF600800ULL,
   1360       (Addr)&VG_(amd64_linux_REDIR_FOR_vgetcpu)
   1361    );
   1362 
   1363    /* If we're using memcheck, use these intercepts right from
   1364       the start, otherwise ld.so makes a lot of noise. */
   1365    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1366 
   1367       add_hardwired_spec(
   1368          "ld-linux-x86-64.so.2", "index",
   1369          (Addr)&VG_(amd64_linux_REDIR_FOR_index), NULL);
   1370       add_hardwired_spec(
   1371          "ld-linux-x86-64.so.2", "strlen",
   1372          (Addr)&VG_(amd64_linux_REDIR_FOR_strlen),
   1373 #        ifndef GLIBC_MANDATORY_STRLEN_REDIRECT
   1374          NULL
   1375 #        else
   1376          /* for glibc-2.10 and later, this is mandatory - can't sanely
   1377             continue without it */
   1378          complain_about_stripped_glibc_ldso
   1379 #        endif
   1380       );
   1381    }
   1382 
   1383 #  elif defined(VGP_ppc32_linux)
   1384    /* If we're using memcheck, use these intercepts right from
   1385       the start, otherwise ld.so makes a lot of noise. */
   1386    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1387 
   1388       /* this is mandatory - can't sanely continue without it */
   1389       add_hardwired_spec(
   1390          "ld.so.1", "strlen",
   1391          (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen),
   1392          complain_about_stripped_glibc_ldso
   1393       );
   1394       add_hardwired_spec(
   1395          "ld.so.1", "strcmp",
   1396          (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp),
   1397          NULL /* not mandatory - so why bother at all? */
   1398          /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
   1399       );
   1400       add_hardwired_spec(
   1401          "ld.so.1", "index",
   1402          (Addr)&VG_(ppc32_linux_REDIR_FOR_strchr),
   1403          NULL /* not mandatory - so why bother at all? */
   1404          /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
   1405       );
   1406    }
   1407 
   1408 #  elif defined(VGP_ppc64be_linux)
   1409    /* If we're using memcheck, use these intercepts right from
   1410       the start, otherwise ld.so makes a lot of noise. */
   1411    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1412 
   1413       /* this is mandatory - can't sanely continue without it */
   1414       add_hardwired_spec(
   1415          "ld64.so.1", "strlen",
   1416          (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ),
   1417          complain_about_stripped_glibc_ldso
   1418       );
   1419 
   1420       add_hardwired_spec(
   1421          "ld64.so.1", "index",
   1422          (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strchr) ),
   1423          NULL /* not mandatory - so why bother at all? */
   1424          /* glibc-2.5 (FC6, ppc64) seems fine without it */
   1425       );
   1426    }
   1427 
   1428 #  elif defined(VGP_ppc64le_linux)
   1429    /* If we're using memcheck, use these intercepts right from
   1430     * the start, otherwise ld.so makes a lot of noise.
   1431     */
   1432    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1433 
   1434       /* this is mandatory - can't sanely continue without it */
   1435       add_hardwired_spec(
   1436          "ld64.so.2", "strlen",
   1437          (Addr)&VG_(ppc64_linux_REDIR_FOR_strlen),
   1438          complain_about_stripped_glibc_ldso
   1439       );
   1440 
   1441       add_hardwired_spec(
   1442          "ld64.so.2", "index",
   1443          (Addr)&VG_(ppc64_linux_REDIR_FOR_strchr),
   1444          NULL /* not mandatory - so why bother at all? */
   1445          /* glibc-2.5 (FC6, ppc64) seems fine without it */
   1446       );
   1447    }
   1448 
   1449 #  elif defined(VGP_arm_linux)
   1450    /* If we're using memcheck, use these intercepts right from the
   1451       start, otherwise ld.so makes a lot of noise.  In most ARM-linux
   1452       distros, ld.so's soname is ld-linux.so.3, but Ubuntu 14.04 on
   1453       Odroid uses ld-linux-armhf.so.3 for some reason. */
   1454    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1455       /* strlen */
   1456       add_hardwired_spec(
   1457          "ld-linux.so.3", "strlen",
   1458          (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
   1459          complain_about_stripped_glibc_ldso
   1460       );
   1461       add_hardwired_spec(
   1462          "ld-linux-armhf.so.3", "strlen",
   1463          (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
   1464          complain_about_stripped_glibc_ldso
   1465       );
   1466       /* memcpy */
   1467       add_hardwired_spec(
   1468          "ld-linux.so.3", "memcpy",
   1469          (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
   1470          complain_about_stripped_glibc_ldso
   1471       );
   1472       add_hardwired_spec(
   1473          "ld-linux-armhf.so.3", "memcpy",
   1474          (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
   1475          complain_about_stripped_glibc_ldso
   1476       );
   1477       /* strcmp */
   1478       add_hardwired_spec(
   1479          "ld-linux.so.3", "strcmp",
   1480          (Addr)&VG_(arm_linux_REDIR_FOR_strcmp),
   1481          complain_about_stripped_glibc_ldso
   1482       );
   1483       add_hardwired_spec(
   1484          "ld-linux-armhf.so.3", "strcmp",
   1485          (Addr)&VG_(arm_linux_REDIR_FOR_strcmp),
   1486          complain_about_stripped_glibc_ldso
   1487       );
   1488    }
   1489 
   1490 #  elif defined(VGP_arm64_linux)
   1491    /* If we're using memcheck, use these intercepts right from
   1492       the start, otherwise ld.so makes a lot of noise. */
   1493    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1494       add_hardwired_spec(
   1495          "ld-linux-aarch64.so.1", "strlen",
   1496          (Addr)&VG_(arm64_linux_REDIR_FOR_strlen),
   1497          complain_about_stripped_glibc_ldso
   1498       );
   1499       add_hardwired_spec(
   1500          "ld-linux-aarch64.so.1", "index",
   1501          (Addr)&VG_(arm64_linux_REDIR_FOR_index),
   1502          NULL
   1503       );
   1504       add_hardwired_spec(
   1505          "ld-linux-aarch64.so.1", "strcmp",
   1506          (Addr)&VG_(arm64_linux_REDIR_FOR_strcmp),
   1507          NULL
   1508       );
   1509 #     if defined(VGPV_arm64_linux_android)
   1510       add_hardwired_spec(
   1511          "NONE", "__dl_strlen", // in /system/bin/linker64
   1512          (Addr)&VG_(arm64_linux_REDIR_FOR_strlen),
   1513          NULL
   1514       );
   1515 #     endif
   1516    }
   1517 
   1518 #  elif defined(VGP_x86_darwin)
   1519    /* If we're using memcheck, use these intercepts right from
   1520       the start, otherwise dyld makes a lot of noise. */
   1521    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1522       add_hardwired_spec("dyld", "strcmp",
   1523                          (Addr)&VG_(x86_darwin_REDIR_FOR_strcmp), NULL);
   1524       add_hardwired_spec("dyld", "strlen",
   1525                          (Addr)&VG_(x86_darwin_REDIR_FOR_strlen), NULL);
   1526       add_hardwired_spec("dyld", "strcat",
   1527                          (Addr)&VG_(x86_darwin_REDIR_FOR_strcat), NULL);
   1528       add_hardwired_spec("dyld", "strcpy",
   1529                          (Addr)&VG_(x86_darwin_REDIR_FOR_strcpy), NULL);
   1530       add_hardwired_spec("dyld", "strlcat",
   1531                          (Addr)&VG_(x86_darwin_REDIR_FOR_strlcat), NULL);
   1532    }
   1533 
   1534 #  elif defined(VGP_amd64_darwin)
   1535    /* If we're using memcheck, use these intercepts right from
   1536       the start, otherwise dyld makes a lot of noise. */
   1537    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1538       add_hardwired_spec("dyld", "strcmp",
   1539                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strcmp), NULL);
   1540       add_hardwired_spec("dyld", "strlen",
   1541                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strlen), NULL);
   1542       add_hardwired_spec("dyld", "strcat",
   1543                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strcat), NULL);
   1544       add_hardwired_spec("dyld", "strcpy",
   1545                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strcpy), NULL);
   1546       add_hardwired_spec("dyld", "strlcat",
   1547                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strlcat), NULL);
   1548       // DDD: #warning fixme rdar://6166275
   1549       add_hardwired_spec("dyld", "arc4random",
   1550                          (Addr)&VG_(amd64_darwin_REDIR_FOR_arc4random), NULL);
   1551 #     if DARWIN_VERS == DARWIN_10_9
   1552       add_hardwired_spec("dyld", "strchr",
   1553                          (Addr)&VG_(amd64_darwin_REDIR_FOR_strchr), NULL);
   1554 #     endif
   1555    }
   1556 
   1557 #  elif defined(VGP_s390x_linux)
   1558    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1559       // added in rsponse to BZ 327943
   1560       add_hardwired_spec("ld64.so.1", "index",
   1561                          (Addr)&VG_(s390x_linux_REDIR_FOR_index),
   1562                          complain_about_stripped_glibc_ldso);
   1563    }
   1564 
   1565 #  elif defined(VGP_mips32_linux)
   1566    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1567 
   1568       /* this is mandatory - can't sanely continue without it */
   1569       add_hardwired_spec(
   1570          "ld.so.1", "strlen",
   1571          (Addr)&VG_(mips32_linux_REDIR_FOR_strlen),
   1572          complain_about_stripped_glibc_ldso
   1573       );
   1574       add_hardwired_spec(
   1575          "ld.so.1", "index",
   1576          (Addr)&VG_(mips32_linux_REDIR_FOR_index),
   1577          complain_about_stripped_glibc_ldso
   1578       );
   1579 #  if defined(VGPV_mips32_linux_android)
   1580       add_hardwired_spec(
   1581          "NONE", "__dl_strlen",
   1582          (Addr)&VG_(mips32_linux_REDIR_FOR_strlen),
   1583          NULL
   1584       );
   1585 #  endif
   1586 
   1587    }
   1588 
   1589 #  elif defined(VGP_mips64_linux)
   1590    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1591 
   1592       /* this is mandatory - can't sanely continue without it */
   1593       add_hardwired_spec(
   1594          "ld.so.1", "strlen",
   1595          (Addr)&VG_(mips64_linux_REDIR_FOR_strlen),
   1596          complain_about_stripped_glibc_ldso
   1597       );
   1598       add_hardwired_spec(
   1599          "ld.so.1", "index",
   1600          (Addr)&VG_(mips64_linux_REDIR_FOR_index),
   1601          complain_about_stripped_glibc_ldso
   1602       );
   1603    }
   1604 
   1605 #  elif defined(VGP_x86_solaris)
   1606    /* If we're using memcheck, use these intercepts right from
   1607       the start, otherwise ld.so makes a lot of noise. */
   1608    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1609       add_hardwired_spec("/lib/ld.so.1", "strcmp",
   1610                          (Addr)&VG_(x86_solaris_REDIR_FOR_strcmp), NULL);
   1611    }
   1612    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1613       add_hardwired_spec("/lib/ld.so.1", "strlen",
   1614                          (Addr)&VG_(x86_solaris_REDIR_FOR_strlen), NULL);
   1615    }
   1616 
   1617 #  elif defined(VGP_amd64_solaris)
   1618    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1619       add_hardwired_spec("/lib/amd64/ld.so.1", "strcpy",
   1620                          (Addr)&VG_(amd64_solaris_REDIR_FOR_strcpy), NULL);
   1621    }
   1622    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1623       add_hardwired_spec("/lib/amd64/ld.so.1", "strncpy",
   1624                          (Addr)&VG_(amd64_solaris_REDIR_FOR_strncpy), NULL);
   1625    }
   1626    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1627       add_hardwired_spec("/lib/amd64/ld.so.1", "strcmp",
   1628                          (Addr)&VG_(amd64_solaris_REDIR_FOR_strcmp), NULL);
   1629    }
   1630    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1631       add_hardwired_spec("/lib/amd64/ld.so.1", "strcat",
   1632                          (Addr)&VG_(amd64_solaris_REDIR_FOR_strcat), NULL);
   1633    }
   1634    if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
   1635       add_hardwired_spec("/lib/amd64/ld.so.1", "strlen",
   1636                          (Addr)&VG_(amd64_solaris_REDIR_FOR_strlen), NULL);
   1637    }
   1638 
   1639 #  else
   1640 #    error Unknown platform
   1641 #  endif
   1642 
   1643    if (VG_(clo_trace_redir))
   1644       show_redir_state("after VG_(redir_initialise)");
   1645 }
   1646 
   1647 
   1648 /*------------------------------------------------------------*/
   1649 /*--- MISC HELPERS                                         ---*/
   1650 /*------------------------------------------------------------*/
   1651 
   1652 static void* dinfo_zalloc(const HChar* ec, SizeT n) {
   1653    void* p;
   1654    vg_assert(n > 0);
   1655    p = VG_(arena_malloc)(VG_AR_DINFO, ec, n);
   1656    VG_(memset)(p, 0, n);
   1657    return p;
   1658 }
   1659 
   1660 static void dinfo_free(void* p) {
   1661    vg_assert(p);
   1662    return VG_(arena_free)(VG_AR_DINFO, p);
   1663 }
   1664 
   1665 static HChar* dinfo_strdup(const HChar* ec, const HChar* str)
   1666 {
   1667    return VG_(arena_strdup)(VG_AR_DINFO, ec, str);
   1668 }
   1669 
   1670 /* Really this should be merged with translations_allowable_from_seg
   1671    in m_translate. */
   1672 static Bool is_plausible_guest_addr(Addr a)
   1673 {
   1674    NSegment const* seg = VG_(am_find_nsegment)(a);
   1675    return seg != NULL
   1676           && (seg->kind == SkAnonC || seg->kind == SkFileC ||
   1677               seg->kind == SkShmC)
   1678           && (seg->hasX || seg->hasR); /* crude x86-specific hack */
   1679 }
   1680 
   1681 
   1682 /*------------------------------------------------------------*/
   1683 /*--- NOTIFY-ON-LOAD FUNCTIONS                             ---*/
   1684 /*------------------------------------------------------------*/
   1685 
   1686 static
   1687 void handle_maybe_load_notifier( const HChar* soname,
   1688                                  const HChar* symbol, Addr addr )
   1689 {
   1690 #  if defined(VGP_x86_linux)
   1691    /* x86-linux only: if we see _dl_sysinfo_int80, note its address.
   1692       See comment on declaration of VG_(client__dl_sysinfo_int80) for
   1693       the reason.  As far as I can tell, the relevant symbol is always
   1694       in object with soname "ld-linux.so.2". */
   1695    if (symbol && symbol[0] == '_'
   1696               && 0 == VG_(strcmp)(symbol, "_dl_sysinfo_int80")
   1697               && 0 == VG_(strcmp)(soname, "ld-linux.so.2")) {
   1698       if (VG_(client__dl_sysinfo_int80) == 0)
   1699          VG_(client__dl_sysinfo_int80) = addr;
   1700    }
   1701 #  endif
   1702 
   1703    /* Normal load-notifier handling after here.  First, ignore all
   1704       symbols lacking the right prefix. */
   1705    vg_assert(symbol); // assert rather than segfault if it is NULL
   1706    if (0 != VG_(strncmp)(symbol, VG_NOTIFY_ON_LOAD_PREFIX,
   1707                                  VG_NOTIFY_ON_LOAD_PREFIX_LEN))
   1708       /* Doesn't have the right prefix */
   1709       return;
   1710 
   1711    if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0)
   1712       VG_(client_freeres_wrapper) = addr;
   1713    else
   1714    if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0)
   1715       iFuncWrapper = addr;
   1716    else
   1717       vg_assert2(0, "unrecognised load notification function: %s", symbol);
   1718 }
   1719 
   1720 
   1721 /*------------------------------------------------------------*/
   1722 /*--- REQUIRE-TEXT-SYMBOL HANDLING                         ---*/
   1723 /*------------------------------------------------------------*/
   1724 
   1725 /* In short: check that the currently-being-loaded object has text
   1726    symbols that satisfy any --require-text-symbol= specifications that
   1727    apply to it, and abort the run with an error message if not.
   1728 */
   1729 static void handle_require_text_symbols ( const DebugInfo* di )
   1730 {
   1731    /* First thing to do is figure out which, if any,
   1732       --require-text-symbol specification strings apply to this
   1733       object.  Most likely none do, since it is not expected to
   1734       frequently be used.  Work through the list of specs and
   1735       accumulate in fnpatts[] the fn patterns that pertain to this
   1736       object. */
   1737    XArray *fnpatts = VG_(newXA)( VG_(malloc), "m_redir.hrts.5",
   1738                                  VG_(free), sizeof(HChar*) );
   1739 
   1740    Int    i, j;
   1741    const HChar* di_soname = VG_(DebugInfo_get_soname)(di);
   1742    vg_assert(di_soname); // must be present
   1743 
   1744    for (i = 0; i < VG_(sizeXA)(VG_(clo_req_tsyms)); i++) {
   1745       const HChar* clo_spec = *(HChar**) VG_(indexXA)(VG_(clo_req_tsyms), i);
   1746       vg_assert(clo_spec && VG_(strlen)(clo_spec) >= 4);
   1747       // clone the spec, so we can stick a zero at the end of the sopatt
   1748       HChar *spec = VG_(strdup)("m_redir.hrts.1", clo_spec);
   1749       HChar sep = spec[0];
   1750       HChar* sopatt = &spec[1];
   1751       HChar* fnpatt = VG_(strchr)(sopatt, sep);
   1752       // the initial check at clo processing in time in m_main
   1753       // should ensure this.
   1754       vg_assert(fnpatt && *fnpatt == sep);
   1755       *fnpatt = 0;
   1756       fnpatt++;
   1757       if (VG_(string_match)(sopatt, di_soname)) {
   1758          HChar *pattern = VG_(strdup)("m_redir.hrts.2", fnpatt);
   1759          VG_(addToXA)(fnpatts, &pattern);
   1760       }
   1761       VG_(free)(spec);
   1762    }
   1763 
   1764    if (VG_(sizeXA)(fnpatts) == 0) {
   1765       VG_(deleteXA)(fnpatts);
   1766       return;  /* no applicable spec strings */
   1767    }
   1768 
   1769    /* So finally, fnpatts contains the set of
   1770       (patterns for) text symbol names that must be found in this
   1771       object, in order to continue.  That is, we must find at least
   1772       one text symbol name that matches each pattern, else we must
   1773       abort the run. */
   1774 
   1775    if (0) VG_(printf)("for %s\n", di_soname);
   1776    for (i = 0; i < VG_(sizeXA)(fnpatts); i++)
   1777       if (0) VG_(printf)("   fnpatt: %s\n",
   1778                          *(HChar**) VG_(indexXA)(fnpatts, i));
   1779 
   1780    /* For each spec, look through the syms to find one that matches.
   1781       This isn't terribly efficient but it happens rarely, so no big
   1782       deal. */
   1783    for (i = 0; i < VG_(sizeXA)(fnpatts); i++) {
   1784       Bool   found  = False;
   1785       const HChar* fnpatt = *(HChar**) VG_(indexXA)(fnpatts, i);
   1786       Int    nsyms  = VG_(DebugInfo_syms_howmany)(di);
   1787       for (j = 0; j < nsyms; j++) {
   1788          Bool    isText        = False;
   1789          const HChar*  sym_name_pri  = NULL;
   1790          const HChar** sym_names_sec = NULL;
   1791          VG_(DebugInfo_syms_getidx)( di, j, NULL,
   1792                                      NULL, &sym_name_pri, &sym_names_sec,
   1793                                      &isText, NULL, NULL );
   1794          const HChar*  twoslots[2];
   1795          const HChar** names_init =
   1796             alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
   1797          const HChar** names;
   1798          for (names = names_init; *names; names++) {
   1799             /* ignore data symbols */
   1800             if (0) VG_(printf)("QQQ %s\n", *names);
   1801             vg_assert(sym_name_pri);
   1802             if (!isText)
   1803                continue;
   1804             if (VG_(string_match)(fnpatt, *names)) {
   1805                found = True;
   1806                break;
   1807             }
   1808          }
   1809          free_symname_array(names_init, &twoslots[0]);
   1810          if (found)
   1811             break;
   1812       }
   1813 
   1814       if (!found) {
   1815          const HChar* v = "valgrind:  ";
   1816          VG_(printf)("\n");
   1817          VG_(printf)(
   1818          "%sFatal error at when loading library with soname\n", v);
   1819          VG_(printf)(
   1820          "%s   %s\n", v, di_soname);
   1821          VG_(printf)(
   1822          "%sCannot find any text symbol with a name "
   1823          "that matches the pattern\n", v);
   1824          VG_(printf)("%s   %s\n", v, fnpatt);
   1825          VG_(printf)("%sas required by a --require-text-symbol= "
   1826          "specification.\n", v);
   1827          VG_(printf)("\n");
   1828          VG_(printf)(
   1829          "%sCannot continue -- exiting now.\n", v);
   1830          VG_(printf)("\n");
   1831          VG_(exit)(1);
   1832       }
   1833    }
   1834 
   1835    /* All required specs were found.  Just free memory and return. */
   1836    for (i = 0; i < VG_(sizeXA)(fnpatts); i++)
   1837       VG_(free)(*(HChar**) VG_(indexXA)(fnpatts, i));
   1838    VG_(deleteXA)(fnpatts);
   1839 }
   1840 
   1841 
   1842 /*------------------------------------------------------------*/
   1843 /*--- SANITY/DEBUG                                         ---*/
   1844 /*------------------------------------------------------------*/
   1845 
   1846 static void show_spec ( const HChar* left, const Spec* spec )
   1847 {
   1848    VG_(message)( Vg_DebugMsg,
   1849                  "%s%-25s %-30s %s%s-> (%04d.%d) 0x%08lx\n",
   1850                  left,
   1851                  spec->from_sopatt, spec->from_fnpatt,
   1852                  spec->isWrap ? "W" : "R",
   1853                  spec->isGlobal ? "G" : "L",
   1854                  spec->becTag, spec->becPrio,
   1855                  spec->to_addr );
   1856 }
   1857 
   1858 static void show_active ( const HChar* left, const Active* act )
   1859 {
   1860    Bool ok;
   1861    const HChar *buf;
   1862 
   1863    ok = VG_(get_fnname_w_offset)(act->from_addr, &buf);
   1864    if (!ok) buf = "???";
   1865    // Stash away name1
   1866    HChar name1[VG_(strlen)(buf) + 1];
   1867    VG_(strcpy)(name1, buf);
   1868 
   1869    const HChar *name2;
   1870    ok = VG_(get_fnname_w_offset)(act->to_addr, &name2);
   1871    if (!ok) name2 = "???";
   1872 
   1873    VG_(message)(Vg_DebugMsg, "%s0x%08lx (%-20s) %s-> (%04d.%d) 0x%08lx %s\n",
   1874                              left,
   1875                              act->from_addr, name1,
   1876                              act->isWrap ? "W" : "R",
   1877                              act->becTag, act->becPrio,
   1878                              act->to_addr, name2 );
   1879 }
   1880 
   1881 static void show_redir_state ( const HChar* who )
   1882 {
   1883    TopSpec* ts;
   1884    Spec*    sp;
   1885    Active*  act;
   1886    VG_(message)(Vg_DebugMsg, "<<\n");
   1887    VG_(message)(Vg_DebugMsg, "   ------ REDIR STATE %s ------\n", who);
   1888    for (ts = topSpecs; ts; ts = ts->next) {
   1889       if (ts->seginfo)
   1890          VG_(message)(Vg_DebugMsg,
   1891                       "   TOPSPECS of soname %s filename %s\n",
   1892                       VG_(DebugInfo_get_soname)(ts->seginfo),
   1893                       VG_(DebugInfo_get_filename)(ts->seginfo));
   1894       else
   1895          VG_(message)(Vg_DebugMsg,
   1896                       "   TOPSPECS of soname (hardwired)\n");
   1897 
   1898       for (sp = ts->specs; sp; sp = sp->next)
   1899          show_spec("     ", sp);
   1900    }
   1901    VG_(message)(Vg_DebugMsg, "   ------ ACTIVE ------\n");
   1902    VG_(OSetGen_ResetIter)( activeSet );
   1903    while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
   1904       show_active("    ", act);
   1905    }
   1906 
   1907    VG_(message)(Vg_DebugMsg, ">>\n");
   1908 }
   1909 
   1910 /*--------------------------------------------------------------------*/
   1911 /*--- end                                                          ---*/
   1912 /*--------------------------------------------------------------------*/
   1913