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