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