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@acm.org
12   Copyright (C) 2003-2010 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_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. */
221typedef
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. */
243typedef
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.) */
256static 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. */
267typedef
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 */
279static OSet* activeSet = NULL;
280
281/* Wrapper routine for indirect functions */
282static Addr iFuncWrapper;
283
284/*------------------------------------------------------------*/
285/*--- FWDses                                               ---*/
286/*------------------------------------------------------------*/
287
288static void maybe_add_active ( Active /*by value; callee copies*/ );
289
290static void*  dinfo_zalloc(HChar* ec, SizeT);
291static void   dinfo_free(void*);
292static HChar* dinfo_strdup(HChar* ec, HChar*);
293static Bool   is_plausible_guest_addr(Addr);
294static Bool   is_aix5_glink_idiom(Addr);
295
296static void   show_redir_state ( HChar* who );
297static void   show_active ( HChar* left, Active* act );
298
299static void   handle_maybe_load_notifier( const UChar* soname,
300                                                HChar* symbol, Addr addr );
301
302static void   handle_require_text_symbols ( DebugInfo* );
303
304/*------------------------------------------------------------*/
305/*--- NOTIFICATIONS                                        ---*/
306/*------------------------------------------------------------*/
307
308static
309void 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
325void 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
490void 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
515static
516void 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. */
639static 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
708void 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. */
812Addr 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 */
836static 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 */
856static 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 */
888static 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
909void 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
1094static 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
1103static void dinfo_free(void* p) {
1104   tl_assert(p);
1105   return VG_(arena_free)(VG_AR_DINFO, p);
1106}
1107
1108static 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. */
1115static 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). */
1128static 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
1165static
1166void 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*/
1206static 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
1310static 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
1320static 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
1338static 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