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