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