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