2 /*--------------------------------------------------------------------*/
3 /*--- Function replacement and wrapping. m_redir.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 Julian Seward
12 Copyright (C) 2003-2010 Jeremy Fitzhardinge
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.
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.
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
30 The GNU General Public License is contained in the file COPYING.
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)
53 #include "config.h" /* GLIBC_2_* */
56 #include "pub_l4re_consts.h"
57 #include "l4re_helper.h"
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
69 The interface is simple. VG_(redir_initialise) initialises and
70 loads some hardwired redirects which never disappear; this is
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
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).
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.
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.
104 /*------------------------------------------------------------*/
105 /*--- Semantics ---*/
106 /*------------------------------------------------------------*/
108 /* The redirector holds two pieces of state:
110 Specs - a set of (soname pattern, fnname pattern) -> redir addr
111 Active - a set of orig addr -> (bool, redir addr)
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.
117 Active is a pure function of Specs and the current symbol table
118 state (maintained by m_debuginfo). Call the latter SyminfoState.
120 Therefore whenever either Specs or SyminfoState changes, Active
121 must be recomputed. [Inefficient if done naively, but this is a
124 Active is computed as follows:
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
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].
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"
147 ---------------------
149 That completes the spec, apart from one difficult issue: duplicates.
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:
156 (libpthread.so, pthread_mutex_lock) -> a1
157 (libpthread.so, pthread_*) -> a2
159 for a1 != a2. Or even hairier:
161 (libpthread.so, pthread_mutex_*) -> a1
162 (libpthread.so, pthread_*_lock) -> a2
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
172 ===========================================================
173 ===========================================================
174 Incremental implementation:
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
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
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.
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.
194 - Finally, add new new specs to the current set of specs.
196 When adding a new active (s,d) to the 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)
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)
210 /*------------------------------------------------------------*/
211 /*--- REDIRECTION SPECIFICATIONS ---*/
212 /*------------------------------------------------------------*/
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.
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. */
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 */
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. */
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 */
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;
263 /*------------------------------------------------------------*/
264 /*--- CURRENTLY ACTIVE REDIRECTIONS ---*/
265 /*------------------------------------------------------------*/
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
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? */
282 /* The active set is a fast lookup table */
283 static OSet* activeSet = NULL;
285 /* Wrapper routine for indirect functions */
286 static Addr iFuncWrapper;
288 /*------------------------------------------------------------*/
290 /*------------------------------------------------------------*/
292 static void maybe_add_active ( Active /*by value; callee copies*/ );
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);
300 static void show_redir_state ( HChar* who );
301 static void show_active ( HChar* left, Active* act );
303 static void handle_maybe_load_notifier( const UChar* soname,
304 HChar* symbol, Addr addr );
306 static void handle_require_text_symbols ( DebugInfo* );
308 /*------------------------------------------------------------*/
309 /*--- NOTIFICATIONS ---*/
310 /*------------------------------------------------------------*/
313 void generate_and_add_actives (
314 /* spec list and the owning TopSpec */
316 TopSpec* parent_spec,
317 /* debuginfo and the owning TopSpec */
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. */
327 #define N_DEMANGLED 256
329 void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
338 Addr sym_addr, sym_toc;
339 HChar demangled_sopatt[N_DEMANGLED];
340 HChar demangled_fnpatt[N_DEMANGLED];
341 Bool check_ppcTOCs = False;
343 const UChar* newsi_soname;
345 # if defined(VG_PLAT_USES_PPCTOC)
346 check_ppcTOCs = True;
350 newsi_soname = VG_(DebugInfo_get_soname)(newsi);
351 vg_assert(newsi_soname != NULL);
353 /* stay sane: we don't already have this. */
354 for (ts = topSpecs; ts; ts = ts->next)
355 vg_assert(ts->seginfo != newsi);
357 /* scan this DebugInfo's symbol table, pulling out and demangling
360 specList = NULL; /* the spec list we're building up */
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 */
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 );
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. */
384 spec = dinfo_zalloc("redir.rnnD.1", sizeof(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 */
401 for (i = 0; i < nsyms; i++) {
402 VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
403 NULL, &sym_name, &isText, NULL );
405 && VG_(maybe_Z_demangle)(
406 sym_name, demangled_sopatt, N_DEMANGLED,
407 demangled_fnpatt, N_DEMANGLED, &isWrap );
409 /* not a redirect. Ignore. */
412 /* has a valid toc pointer. Ignore. */
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))
420 /* a redirect to some other copy of that symbol, which
421 does have a TOC value, already exists */
425 VG_(message)(Vg_DebugMsg,
426 "WARNING: no TOC ptr for redir/wrap to %s %s\n",
427 demangled_sopatt, demangled_fnpatt);
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));
435 newts->next = NULL; /* not significant */
436 newts->seginfo = newsi;
437 newts->specs = specList;
438 newts->mark = False; /* not significant */
440 /* We now need to augment the active set with the following partial
443 (1) actives formed by matching the new specs in specList against
444 all symbols currently listed in topSpecs
446 (2) actives formed by matching the new symbols in newsi against
447 all specs currently listed in topSpecs
449 (3) actives formed by matching the new symbols in newsi against
450 the new specs in specList
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).
458 for (ts = topSpecs; ts; ts = ts->next) {
460 generate_and_add_actives( specList, newts,
465 for (ts = topSpecs; ts; ts = ts->next) {
466 generate_and_add_actives( ts->specs, ts,
471 generate_and_add_actives( specList, newts,
474 /* Finally, add the new TopSpec. */
475 newts->next = topSpecs;
478 if (VG_(clo_trace_redir))
479 show_redir_state("after VG_(redir_notify_new_DebugInfo)");
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);
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. */
494 void VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from )
498 old = VG_(OSetGen_Lookup)(activeSet, &old_from);
500 vg_assert(old->isIFunc);
503 new.from_addr = new_from;
505 maybe_add_active (new);
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 );
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. */
520 void generate_and_add_actives (
521 /* spec list and the owning TopSpec */
523 TopSpec* parent_spec,
524 /* seginfo and the owning TopSpec */
530 Bool anyMark, isText, isIFunc;
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. */
540 for (sp = specs; sp; sp = sp->next) {
542 sp->mark = VG_(string_match)( sp->from_sopatt,
543 VG_(DebugInfo_get_soname)(di) );
544 anyMark = anyMark || sp->mark;
547 /* shortcut: if none of the sonames match, there will be no bindings. */
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 );
558 /* ignore data symbols */
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))
572 for (sp = specs; sp; sp = sp->next) {
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;
584 maybe_add_active( act );
586 } /* for (sp = specs; sp; sp = sp->next) */
587 } /* for (i = 0; i < nsyms; i++) */
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) {
595 if (sp->mark && (!sp->done) && sp->mandatory)
600 HChar* v = "valgrind: ";
602 vg_assert(!sp->done);
603 vg_assert(sp->mandatory);
606 "%sFatal error at startup: a function redirection\n", v);
608 "%swhich is mandatory for this platform-tool combination\n", v);
610 "%scannot be set up. Details of the redirection are:\n", v);
614 "%sA must-be-redirected function\n", v);
616 "%swhose name matches the pattern: %s\n", v, sp->from_fnpatt);
618 "%sin an object with soname matching: %s\n", v, sp->from_sopatt);
620 "%swas not found whilst processing\n", v);
622 "%ssymbols from the object with soname: %s\n",
623 v, VG_(DebugInfo_get_soname)(di));
627 for (strp = sp->mandatory; *strp; strp++)
634 "%sCannot continue -- exiting now. Sorry.\n", v);
641 /* Add an act (passed by value; is copied here) and deal with
642 conflicting bindings. */
643 static void maybe_add_active ( Active act )
648 /* Complain and ignore manifestly bogus 'from' addresses.
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.
654 amd64-linux hack: the vsysinfo pages appear to have no
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
663 # if defined(VGO_l4re)
664 && act.from_addr != SYSCALL_PAGE
667 what = "redirection from-address is in non-executable area";
671 old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr );
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";
681 /* This appears to be a duplicate of an existing binding.
682 Safe(ish) -- ignore. */
683 /* XXXXXXXXXXX COMPLAIN if new and old parents differ */
686 Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
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
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)");
704 if (VG_(clo_verbosity) > 1) {
705 VG_(message)(Vg_UserMsg, "WARNING: %s\n", what);
706 show_active( " new: ", &act);
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. */
715 void VG_(redir_notify_delete_DebugInfo)( DebugInfo* delsi )
728 /* Search for it, and make tsPrev point to the previous entry, if
733 if (ts == NULL) break;
734 if (ts->seginfo == delsi) break;
739 vg_assert(ts); /* else we don't have the deleted DebugInfo */
740 vg_assert(ts->seginfo == delsi);
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);
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);
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. */
761 && act->parent_spec != NULL
762 && act->parent_sym != NULL ) {
763 if (!is_plausible_guest_addr(act->from_addr))
765 if (!is_plausible_guest_addr(act->to_addr))
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)");
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 );
785 VG_(OSetGen_FreeNode)( activeSet, act );
788 VG_(OSetWord_Destroy)( tmpSet );
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);
799 if (tsPrev == NULL) {
803 tsPrev->next = ts->next;
807 if (VG_(clo_trace_redir))
808 show_redir_state("after VG_(redir_notify_delete_DebugInfo)");
812 /*------------------------------------------------------------*/
813 /*--- QUERIES (really the whole point of this module) ---*/
814 /*------------------------------------------------------------*/
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 )
821 Active* r = VG_(OSetGen_Lookup)(activeSet, &orig);
825 vg_assert(r->to_addr != 0);
827 *isWrap = r->isWrap || r->isIFunc;
829 vg_assert(iFuncWrapper);
836 /*------------------------------------------------------------*/
837 /*--- INITIALISATION ---*/
838 /*------------------------------------------------------------*/
840 /* Add a never-delete-me Active. */
842 __attribute__((unused)) /* only used on amd64 */
843 static void add_hardwired_active ( Addr from, Addr to )
846 act.from_addr = from;
848 act.parent_spec = NULL;
849 act.parent_sym = NULL;
852 maybe_add_active( act );
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. */
862 __attribute__((unused)) /* not used on all platforms */
863 static void add_hardwired_spec ( HChar* sopatt, HChar* fnpatt,
865 const HChar** mandatory )
867 Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec));
870 if (topSpecs == NULL) {
871 topSpecs = dinfo_zalloc("redir.ahs.2", sizeof(TopSpec));
873 /* symtab_zalloc sets all fields to zero */
876 vg_assert(topSpecs != NULL);
877 vg_assert(topSpecs->next == NULL);
878 vg_assert(topSpecs->seginfo == NULL);
880 spec->from_sopatt = sopatt;
881 spec->from_fnpatt = fnpatt;
882 spec->to_addr = to_addr;
883 spec->isWrap = False;
884 spec->mandatory = mandatory;
886 spec->mark = False; /* not significant */
887 spec->done = False; /* not significant */
889 spec->next = topSpecs->specs;
890 topSpecs->specs = spec;
894 __attribute__((unused)) /* not used on all platforms */
895 static void add_hardwired_wrap ( HChar* sopatt, HChar* fnpatt,
897 const HChar** mandatory )
899 Spec* spec = dinfo_zalloc("redir.ahs.1", sizeof(Spec));
902 if (topSpecs == NULL) {
903 topSpecs = dinfo_zalloc("redir.ahs.2", sizeof(TopSpec));
905 /* symtab_zalloc sets all fields to zero */
908 vg_assert(topSpecs != NULL);
909 vg_assert(topSpecs->next == NULL);
910 vg_assert(topSpecs->seginfo == NULL);
912 spec->from_sopatt = sopatt;
913 spec->from_fnpatt = fnpatt;
914 spec->to_addr = to_addr;
916 spec->mandatory = mandatory;
918 spec->mark = False; /* not significant */
919 spec->done = False; /* not significant */
921 spec->next = topSpecs->specs;
922 topSpecs->specs = spec;
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",
936 " On Debian, Ubuntu: libc6-dbg",
937 " On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo",
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. */
948 void VG_(redir_initialise) ( void )
950 // Assert that there are no DebugInfos so far
951 vg_assert( VG_(next_DebugInfo)(NULL) == NULL );
953 // Initialise active mapping.
954 activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr),
955 NULL, // Use fast comparison
960 // The rest of this function just adds initial Specs.
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)
973 /* for glibc-2.12 and later, this is mandatory - can't sanely
974 continue without it */
975 mandatory = complain_about_stripped_glibc_ldso;
978 "ld-linux.so.2", "index",
979 (Addr)&VG_(x86_linux_REDIR_FOR_index), mandatory);
981 "ld-linux.so.2", "strlen",
982 (Addr)&VG_(x86_linux_REDIR_FOR_strlen), mandatory);
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)
991 add_hardwired_active(
992 0xFFFFFFFFFF600400ULL,
993 (Addr)&VG_(amd64_linux_REDIR_FOR_vtime)
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)) {
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)
1008 /* for glibc-2.10 and later, this is mandatory - can't sanely
1009 continue without it */
1010 complain_about_stripped_glibc_ldso
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)) {
1020 /* this is mandatory - can't sanely continue without it */
1022 "ld.so.1", "strlen",
1023 (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen),
1024 complain_about_stripped_glibc_ldso
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 */
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 */
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)) {
1045 /* this is mandatory - can't sanely continue without it */
1047 "ld64.so.1", "strlen",
1048 (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ),
1049 complain_about_stripped_glibc_ldso
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 */
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)) {
1065 "ld-linux.so.3", "strlen",
1066 (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
1067 complain_about_stripped_glibc_ldso
1069 //add_hardwired_spec(
1070 // "ld-linux.so.3", "index",
1071 // (Addr)&VG_(arm_linux_REDIR_FOR_index),
1075 "ld-linux.so.3", "memcpy",
1076 (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
1077 complain_about_stripped_glibc_ldso
1080 /* nothing so far */
1082 # elif defined(VGP_ppc32_aix5)
1083 /* nothing so far */
1085 # elif defined(VGP_ppc64_aix5)
1086 /* nothing so far */
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);
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);
1123 # elif defined(VGP_s390x_linux)
1124 /* nothing so far */
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",
1131 (Addr)&VG_(x86_l4re_REDIR_FOR_dl_open), NULL);
1132 add_hardwired_wrap("NONE",
1134 (Addr)&VG_(x86_l4re_REDIR_FOR_dl_close), NULL);
1135 add_hardwired_wrap("NONE",
1137 (Addr)&VG_(x86_l4re_REDIR_FOR_dl_mmap), NULL);
1139 # error Unknown platform
1142 if (VG_(clo_trace_redir))
1143 show_redir_state("after VG_(redir_initialise)");
1147 /*------------------------------------------------------------*/
1148 /*--- MISC HELPERS ---*/
1149 /*------------------------------------------------------------*/
1151 static void* dinfo_zalloc(HChar* ec, SizeT n) {
1154 p = VG_(arena_malloc)(VG_AR_DINFO, ec, n);
1156 VG_(memset)(p, 0, n);
1160 static void dinfo_free(void* p) {
1162 return VG_(arena_free)(VG_AR_DINFO, p);
1165 static HChar* dinfo_strdup(HChar* ec, HChar* str)
1167 return VG_(arena_strdup)(VG_AR_DINFO, ec, str);
1170 /* Really this should be merged with translations_allowable_from_seg
1172 static Bool is_plausible_guest_addr(Addr a)
1174 NSegment const* seg = VG_(am_find_nsegment)(a);
1176 && (seg->kind == SkAnonC || seg->kind == SkFileC)
1177 && (seg->hasX || seg->hasR); /* crude x86-specific hack */
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
1185 static Bool is_aix5_glink_idiom ( Addr sym_addr )
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 */)
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 */)
1218 /*------------------------------------------------------------*/
1219 /*--- NOTIFY-ON-LOAD FUNCTIONS ---*/
1220 /*------------------------------------------------------------*/
1223 void handle_maybe_load_notifier( const UChar* soname,
1224 HChar* symbol, Addr addr )
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;
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 */
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;
1252 vg_assert2(0, "unrecognised load notification function: %s", symbol);
1256 /*------------------------------------------------------------*/
1257 /*--- REQUIRE-TEXT-SYMBOL HANDLING ---*/
1258 /*------------------------------------------------------------*/
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.
1264 static void handle_require_text_symbols ( DebugInfo* di )
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
1272 HChar* fnpatts[VG_CLO_MAX_REQ_TSYMS];
1273 Int fnpatts_used = 0;
1275 const HChar* di_soname = VG_(DebugInfo_get_soname)(di);
1276 vg_assert(di_soname); // must be present
1278 VG_(memset)(&fnpatts, 0, sizeof(fnpatts));
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);
1295 if (VG_(string_match)(sopatt, di_soname))
1296 fnpatts[fnpatts_used++]
1297 = VG_(strdup)("m_redir.hrts.2", fnpatt);
1301 if (fnpatts_used == 0)
1302 return; /* no applicable spec strings */
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
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]);
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
1317 for (i = 0; i < fnpatts_used; i++) {
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);
1331 if (VG_(string_match)(fnpatt, sym_name)) {
1338 HChar* v = "valgrind: ";
1341 "%sFatal error at when loading library with soname\n", v);
1343 "%s %s\n", v, di_soname);
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);
1352 "%sCannot continue -- exiting now.\n", v);
1358 /* All required specs were found. Just free memory and return. */
1359 for (i = 0; i < fnpatts_used; i++)
1360 VG_(free)(fnpatts[i]);
1364 /*------------------------------------------------------------*/
1365 /*--- SANITY/DEBUG ---*/
1366 /*------------------------------------------------------------*/
1368 static void show_spec ( HChar* left, Spec* spec )
1370 VG_(message)( Vg_DebugMsg,
1371 "%s%25s %30s %s-> 0x%08llx\n",
1373 spec->from_sopatt, spec->from_fnpatt,
1374 spec->isWrap ? "W" : "R",
1375 (ULong)spec->to_addr );
1378 static void show_active ( HChar* left, Active* act )
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, "???");
1389 VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> 0x%08llx %s\n",
1391 (ULong)act->from_addr, name1,
1392 act->isWrap ? "W" : "R",
1393 (ULong)act->to_addr, name2 );
1396 static void show_redir_state ( HChar* who )
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",
1407 ? (HChar*)VG_(DebugInfo_get_soname)(ts->seginfo)
1409 for (sp = ts->specs; sp; sp = sp->next)
1412 VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------\n");
1413 VG_(OSetGen_ResetIter)( activeSet );
1414 while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
1415 show_active(" ", act);
1418 VG_(message)(Vg_DebugMsg, ">>\n");
1421 /*--------------------------------------------------------------------*/
1423 /*--------------------------------------------------------------------*/