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-2017 Julian Seward
12 Copyright (C) 2003-2017 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, see <http://www.gnu.org/licenses/>.
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_debuglog.h"
33 #include "pub_core_debuginfo.h"
34 #include "pub_core_libcbase.h"
35 #include "pub_core_libcassert.h"
36 #include "pub_core_libcprint.h"
37 #include "pub_core_vki.h"
38 #include "pub_core_libcfile.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_freeres_wrapper)
51 #include "pub_core_demangle.h" // VG_(maybe_Z_demangle)
52 #include "pub_core_libcproc.h" // VG_(libdir)
54 #include "config.h" /* GLIBC_MANDATORY_*_REDIRECT */
57 /* This module is a critical part of the redirection/intercept system.
58 It keeps track of the current intercept state, cleans up the
59 translation caches when that state changes, and finally, answers
60 queries about the whether an address is currently redirected or
61 not. It doesn't do any of the control-flow trickery needed to put
62 the redirections into practice. That is the job of m_translate,
63 which calls here to find out which translations need to be
66 The interface is simple. VG_(redir_initialise) initialises and
67 loads some hardwired redirects which never disappear; this is
70 The module is notified of redirection state changes by m_debuginfo.
71 That calls VG_(redir_notify_new_DebugInfo) when a new DebugInfo
72 (shared object symbol table, basically) appears. Appearance of new
73 symbols can cause new (active) redirections to appear for two
74 reasons: the symbols in the new table may match existing
75 redirection specifications (see comments below), and because the
76 symbols in the new table may themselves supply new redirect
77 specifications which match existing symbols (or ones in the new
80 Redirect specifications are really symbols with "funny" prefixes
81 (_vgrNNNNZU_ and _vgrNNNNZZ_). These names tell m_redir that the
82 associated code should replace the standard entry point for some
83 set of functions. The set of functions is specified by a (soname
84 pattern, function name pattern) pair which is encoded in the symbol
85 name following the prefix. The names use a Z-encoding scheme so
86 that they may contain punctuation characters and wildcards (*).
87 The encoding scheme is described in pub_tool_redir.h and is decoded
88 by VG_(maybe_Z_demangle). The NNNN are behavioural equivalence
89 class tags, and are used to by code in this module to resolve
90 situations where one address appears to be redirected to more than
91 one replacement/wrapper. This is also described in
94 When a shared object is unloaded, this module learns of it via a
95 call to VG_(redir_notify_delete_DebugInfo). It then removes from
96 its tables all active redirections in any way associated with that
97 object, and tidies up the translation caches accordingly.
99 That takes care of tracking the redirection state. When a
100 translation is actually to be made, m_translate calls to
101 VG_(redir_do_lookup) in this module to find out if the
102 translation's address should be redirected.
105 /*------------------------------------------------------------*/
106 /*--- Semantics ---*/
107 /*------------------------------------------------------------*/
109 /* The redirector holds two pieces of state:
111 Specs - a set of (soname pattern, fnname pattern) -> redir addr
112 Active - a set of orig addr -> (bool, redir addr)
114 Active is the currently active set of bindings that the translator
115 consults. Specs is the current set of specifications as harvested
116 from reading symbol tables of the currently loaded objects.
118 Active is a pure function of Specs and the current symbol table
119 state (maintained by m_debuginfo). Call the latter SyminfoState.
121 Therefore whenever either Specs or SyminfoState changes, Active
122 must be recomputed. [Inefficient if done naively, but this is a
125 Active is computed as follows:
129 sopatt = spec.soname pattern
130 fnpatt = spec.fnname pattern
131 redir = spec.redir addr
132 for so matching sopatt in SyminfoState {
133 for fn matching fnpatt in fnnames_of(so) {
134 &fn -> redir is added to Active
139 [as an implementation detail, when a binding (orig -> redir) is
140 deleted from Active as a result of recomputing it, then all
141 translations intersecting redir must be deleted. However, this is
142 not part of the spec].
144 [Active also depends on where the aspacemgr has decided to put all
145 the pieces of code -- that affects the "orig addr" and "redir addr"
148 ---------------------
150 That completes the spec, apart from one difficult issue: duplicates.
152 Clearly we must impose the requirement that domain(Active) contains
153 no duplicates. The difficulty is how to constrain Specs enough to
154 avoid getting into that situation. It's easy to write specs which
155 could cause conflicting bindings in Active, eg:
157 (libpthread.so, pthread_mutex_lock) -> a1
158 (libpthread.so, pthread_*) -> a2
160 for a1 != a2. Or even hairier:
162 (libpthread.so, pthread_mutex_*) -> a1
163 (libpthread.so, pthread_*_lock) -> a2
165 I can't think of any sane way of detecting when an addition to
166 Specs would generate conflicts. However, considering we don't
167 actually want to have a system that allows this, I propose this:
168 all changes to Specs are acceptable. But, when recomputing Active
169 following the change, if the same orig is bound to more than one
170 redir, then the first binding for orig is retained, and all the
173 ===========================================================
174 ===========================================================
175 Incremental implementation:
177 When a new DebugInfo appears:
178 - it may be the source of new specs
179 - it may be the source of new matches for existing specs
182 - (new Specs x existing DebugInfos): scan all symbols in the new
183 DebugInfo to find new specs. Each of these needs to be compared
184 against all symbols in all the existing DebugInfos to generate
187 - (existing Specs x new DebugInfo): scan all symbols in the
188 DebugInfo, trying to match them to any existing specs, also
189 generating new actives.
191 - (new Specs x new DebugInfo): scan all symbols in the new
192 DebugInfo, trying to match them against the new specs, to
193 generate new actives.
195 - Finally, add new new specs to the current set of specs.
197 When adding a new active (s,d) to the Actives:
199 if already bound to d, ignore
200 if already bound to something other than d, complain loudly and ignore
201 else add (s,d) to Actives
202 and discard (s,1) and (d,1) (maybe overly conservative)
204 When a DebugInfo disappears:
205 - delete all specs acquired from the seginfo
206 - delete all actives derived from the just-deleted specs
207 - if each active (s,d) deleted, discard (s,1) and (d,1)
211 /*------------------------------------------------------------*/
212 /*--- REDIRECTION SPECIFICATIONS ---*/
213 /*------------------------------------------------------------*/
215 /* A specification of a redirection we want to do. Note that because
216 both the "from" soname and function name may contain wildcards, the
217 spec can match an arbitrary number of times.
219 16 Nov 2007: Comments re .mandatory field: The initial motivation
220 for this is making Memcheck work sanely on glibc-2.6.X ppc32-linux.
221 We really need to intercept 'strlen' in ld.so right from startup.
222 If ld.so does not have a visible 'strlen' symbol, Memcheck
223 generates an impossible number of errors resulting from highly
224 tuned strlen implementation in ld.so, and is completely unusable
225 -- the resulting undefinedness eventually seeps everywhere. */
228 struct _Spec
* next
; /* linked list */
229 /* FIXED PARTS -- set when created and not changed */
230 HChar
* from_sopatt
; /* from soname pattern */
231 HChar
* from_fnpatt
; /* from fnname pattern */
232 Addr to_addr
; /* where redirecting to */
233 Bool isWrap
; /* wrap or replacement? */
234 Bool isGlobal
; /* must the symbol to replace be global? */
235 Int becTag
; /* 0 through 9999. Behavioural equivalance class tag.
236 If two wrappers have the same (non-zero) tag, they
237 are promising that they behave identically. */
238 Int becPrio
; /* 0 through 9. Behavioural equivalence class prio.
239 Used to choose between competing wrappers with
240 the same (non-zero) tag. */
241 const HChar
** mandatory
; /* non-NULL ==> abort V and print the
242 strings if from_sopatt is loaded but
243 from_fnpatt cannot be found */
244 /* VARIABLE PARTS -- used transiently whilst processing redirections */
245 Bool mark
; /* set if spec requires further processing */
246 Bool done
; /* set if spec was successfully matched */
250 /* Top-level data structure. It contains a pointer to a DebugInfo and
251 also a list of the specs harvested from that DebugInfo. Note that
252 seginfo is allowed to be NULL, meaning that the specs are
253 pre-loaded ones at startup and are not associated with any
254 particular seginfo. */
257 struct _TopSpec
* next
; /* linked list */
258 DebugInfo
* seginfo
; /* symbols etc */
259 Spec
* specs
; /* specs pulled out of seginfo */
260 Bool mark
; /* transient temporary used during deletion */
264 /* This is the top level list of redirections. m_debuginfo maintains
265 a list of DebugInfos, and the idea here is to maintain a list with
266 the same number of elements (in fact, with one more element, so as
267 to record abovementioned preloaded specifications.) */
268 static TopSpec
* topSpecs
= NULL
;
271 /*------------------------------------------------------------*/
272 /*--- CURRENTLY ACTIVE REDIRECTIONS ---*/
273 /*------------------------------------------------------------*/
275 /* Represents a currently active binding. If either parent_spec or
276 parent_sym is NULL, then this binding was hardwired at startup and
277 should not be deleted. Same is true if either parent's seginfo
281 Addr from_addr
; /* old addr -- MUST BE THE FIRST WORD! */
282 Addr to_addr
; /* where redirecting to */
283 TopSpec
* parent_spec
; /* the TopSpec which supplied the Spec */
284 TopSpec
* parent_sym
; /* the TopSpec which supplied the symbol */
285 Int becTag
; /* behavioural eclass tag for ::to_addr */
286 Int becPrio
; /* and its priority */
287 Bool isWrap
; /* wrap or replacement? */
288 Bool isIFunc
; /* indirect function? */
292 /* The active set is a fast lookup table */
293 static OSet
* activeSet
= NULL
;
295 /* Wrapper routine for indirect functions */
296 static Addr iFuncWrapper
;
298 /*------------------------------------------------------------*/
300 /*------------------------------------------------------------*/
302 static void maybe_add_active ( Active
/*by value; callee copies*/ );
304 static void* dinfo_zalloc(const HChar
* ec
, SizeT
);
305 static void dinfo_free(void*);
306 static HChar
* dinfo_strdup(const HChar
* ec
, const HChar
*);
307 static Bool
is_plausible_guest_addr(Addr
);
309 static void show_redir_state ( const HChar
* who
);
310 static void show_active ( const HChar
* left
, const Active
* act
);
312 static void handle_maybe_load_notifier( const HChar
* soname
,
313 const HChar
* symbol
, Addr addr
);
315 static void handle_require_text_symbols ( DebugInfo
* );
317 /*------------------------------------------------------------*/
318 /*--- NOTIFICATIONS ---*/
319 /*------------------------------------------------------------*/
322 void generate_and_add_actives (
323 /* spec list and the owning TopSpec */
325 TopSpec
* parent_spec
,
326 /* debuginfo and the owning TopSpec */
332 /* Copy all the names from a given symbol into an AR_DINFO allocated,
333 NULL terminated array, for easy iteration. Caller must pass also
334 the address of a 2-entry array which can be used in the common case
335 to avoid dynamic allocation. */
336 static const HChar
** alloc_symname_array ( const HChar
* pri_name
,
337 const HChar
** sec_names
,
338 const HChar
** twoslots
)
340 /* Special-case the common case: only one name. We expect the
341 caller to supply a stack-allocated 2-entry array for this. */
342 if (sec_names
== NULL
) {
343 twoslots
[0] = pri_name
;
347 /* Else must use dynamic allocation. Figure out size .. */
349 const HChar
** pp
= sec_names
;
350 while (*pp
) { n_req
++; pp
++; }
351 /* .. allocate and copy in. */
352 const HChar
** arr
= dinfo_zalloc("redir.asa.1", (n_req
+1) * sizeof(HChar
*));
356 while (*pp
) { arr
[i
++] = *pp
; pp
++; }
357 vg_assert(i
== n_req
);
358 vg_assert(arr
[n_req
] == NULL
);
363 /* Free the array allocated by alloc_symname_array, if any. */
364 static void free_symname_array ( const HChar
** names
, const HChar
** twoslots
)
366 if (names
!= twoslots
)
370 static HChar
const* advance_to_equal ( HChar
const* c
) {
371 while (*c
&& *c
!= '=') {
376 static HChar
const* advance_to_comma ( HChar
const* c
) {
377 while (*c
&& *c
!= ',') {
383 /* Notify m_redir of the arrival of a new DebugInfo. This is fairly
384 complex, but the net effect is to (1) add a new entry to the
385 topspecs list, and (2) figure out what new binding are now active,
386 and, as a result, add them to the actives mapping. */
388 void VG_(redir_notify_new_DebugInfo
)( DebugInfo
* newdi
)
390 Bool ok
, isWrap
, isGlobal
;
391 Int i
, nsyms
, becTag
, becPrio
;
396 const HChar
* sym_name_pri
;
397 const HChar
** sym_names_sec
;
399 const HChar
* demangled_sopatt
;
400 const HChar
* demangled_fnpatt
;
401 Bool check_ppcTOCs
= False
;
403 const HChar
* newdi_soname
;
404 Bool dehacktivate_pthread_stack_cache_var_search
= False
;
405 const HChar
* const pthread_soname
= "libpthread.so.0";
406 const HChar
* const pthread_stack_cache_actsize_varname
407 = "stack_cache_actsize";
408 const HChar
* const libc_soname
= "libc.so.6";
409 const HChar
* const libc_gnu_get_libc_version_funcname
= "gnu_get_libc_version";
410 #if defined(VGO_solaris)
411 Bool vg_vfork_fildes_var_search
= False
;
412 const HChar
* const vg_preload_core_soname
= "vgpreload_core.so.0";
413 const HChar
* const vg_vfork_fildes_varname
= "vg_vfork_fildes";
416 # if defined(VG_PLAT_USES_PPCTOC)
417 check_ppcTOCs
= True
;
421 newdi_soname
= VG_(DebugInfo_get_soname
)(newdi
);
422 vg_assert(newdi_soname
!= NULL
);
424 /* libc is special, because it contains some of the core redirects.
425 Make sure it is fully loaded. */
426 if (0 == VG_(strcmp
)(newdi_soname
, libc_soname
) ||
427 0 == VG_(strcmp
)(newdi_soname
, pthread_soname
))
428 VG_(di_load_di
)(newdi
);
432 /* When an outer Valgrind is executing an inner Valgrind, the
433 inner "sees" in its address space the mmap-ed vgpreload files
434 of the outer. The inner must avoid interpreting the
435 redirections given in the outer vgpreload mmap-ed files.
436 Otherwise, some tool combinations badly fail.
438 Example: outer memcheck tool executing an inner none tool.
440 If inner none interprets the outer malloc redirection, the
441 inner will redirect malloc to a memcheck function it does not
442 have (as the redirection target is from the outer). With
443 such a failed redirection, a call to malloc inside the inner
444 will then result in a "no-operation" (and so no memory will
447 When running as an inner, no redirection will be done
448 for a vgpreload file if this file is not located in the
449 inner VALGRIND_LIB directory.
451 Recognising a vgpreload file based on a filename pattern
452 is a kludge. An alternate solution would be to change
453 the _vgr prefix according to outer/inner/client.
455 const HChar
* newdi_filename
= VG_(DebugInfo_get_filename
)(newdi
);
456 const HChar
* newdi_basename
= VG_(basename
) (newdi_filename
);
457 if (VG_(strncmp
) (newdi_basename
, "vgpreload_", 10) == 0) {
458 /* This looks like a vgpreload file => check if this file
459 is from the inner VALGRIND_LIB.
460 We do this check using VG_(stat) + dev/inode comparison
461 as vg-in-place defines a VALGRIND_LIB with symlinks
462 pointing to files inside the valgrind build directories. */
463 struct vg_stat newdi_stat
;
465 struct vg_stat in_vglib_stat
;
468 newdi_res
= VG_(stat
)(newdi_filename
, &newdi_stat
);
470 HChar in_vglib_filename
[VG_(strlen
)(VG_(libdir
)) + 1 +
471 VG_(strlen
)(newdi_basename
) + 1];
472 VG_(sprintf
)(in_vglib_filename
, "%s/%s", VG_(libdir
), newdi_basename
);
474 in_vglib_res
= VG_(stat
)(in_vglib_filename
, &in_vglib_stat
);
476 /* If we find newdi_basename in inner VALGRIND_LIB
477 but newdi_filename is not the same file, then we do
478 not execute the redirection. */
479 if (!sr_isError(in_vglib_res
)
480 && !sr_isError(newdi_res
)
481 && (newdi_stat
.dev
!= in_vglib_stat
.dev
482 || newdi_stat
.ino
!= in_vglib_stat
.ino
)) {
483 /* <inner VALGRIND_LIB>/newdi_basename is an existing file
484 and is different of newdi_filename.
485 So, we do not execute newdi_filename redirection. */
486 if ( VG_(clo_verbosity
) > 1 ) {
487 VG_(message
)( Vg_DebugMsg
,
488 "Skipping vgpreload redir in %s"
489 " (not from VALGRIND_LIB_INNER)\n",
494 if ( VG_(clo_verbosity
) > 1 ) {
495 VG_(message
)( Vg_DebugMsg
,
496 "Executing vgpreload redir in %s"
497 " (from VALGRIND_LIB_INNER)\n",
506 /* stay sane: we don't already have this. */
507 for (ts
= topSpecs
; ts
; ts
= ts
->next
)
508 vg_assert(ts
->seginfo
!= newdi
);
510 /* scan this DebugInfo's symbol table, pulling out and demangling
513 specList
= NULL
; /* the spec list we're building up */
515 dehacktivate_pthread_stack_cache_var_search
=
516 SimHintiS(SimHint_no_nptl_pthread_stackcache
, VG_(clo_sim_hints
))
517 && (0 == VG_(strcmp
)(newdi_soname
, pthread_soname
) ||
518 0 == VG_(strcmp
)(newdi_soname
, libc_soname
));
520 #if defined(VGO_solaris)
521 vg_vfork_fildes_var_search
=
522 0 == VG_(strcmp
)(newdi_soname
, vg_preload_core_soname
);
525 nsyms
= VG_(DebugInfo_syms_howmany
)( newdi
);
526 for (i
= 0; i
< nsyms
; i
++) {
527 VG_(DebugInfo_syms_getidx
)( newdi
, i
, &sym_avmas
,
528 NULL
, &sym_name_pri
, &sym_names_sec
,
529 &isText
, NULL
, NULL
);
530 /* Set up to conveniently iterate over all names for this symbol. */
531 const HChar
* twoslots
[2];
532 const HChar
** names_init
=
533 alloc_symname_array(sym_name_pri
, sym_names_sec
, &twoslots
[0]);
535 for (names
= names_init
; *names
; names
++) {
537 * For Ada demangling, the language doesn't use a regular
538 * prefix like _Z or _R, so look for a common symbol and
541 if (!isText
&& VG_(strcmp
)(*names
, "__gnat_ada_main_program_name") == 0) {
542 VG_(lang_is_ada
) = True
;
545 ok
= VG_(maybe_Z_demangle
)( *names
,
548 &isWrap
, &becTag
, &becPrio
);
550 if (isText
&& dehacktivate_pthread_stack_cache_var_search
) {
551 if (0 == VG_(strcmp
)(*names
, libc_gnu_get_libc_version_funcname
)) {
552 if ( VG_(clo_verbosity
) > 1 ) {
553 VG_(message
)( Vg_DebugMsg
,
554 "deactivate nptl pthread stackcache via tunable:"
555 " found symbol %s at addr %p\n",
556 *names
, (void*) sym_avmas
.main
);
558 VG_(client__gnu_get_libc_version_addr
) = (client__gnu_get_libc_version_type
) sym_avmas
.main
;
559 dehacktivate_pthread_stack_cache_var_search
= False
;
563 /* ignore data symbols */
565 /* But search for dehacktivate stack cache var if needed. */
566 if (dehacktivate_pthread_stack_cache_var_search
567 && 0 == VG_(strcmp
)(*names
,
568 pthread_stack_cache_actsize_varname
)) {
569 if ( VG_(clo_verbosity
) > 1 ) {
570 VG_(message
)( Vg_DebugMsg
,
571 "deactivate nptl pthread stackcache via kludge:"
572 " found symbol %s at addr %p\n",
573 *names
, (void*) sym_avmas
.main
);
575 VG_(client__stack_cache_actsize__addr
) = (SizeT
*) sym_avmas
.main
;
576 dehacktivate_pthread_stack_cache_var_search
= False
;
578 #if defined(VGO_solaris)
579 if (vg_vfork_fildes_var_search
580 && 0 == VG_(strcmp
)(*names
, vg_vfork_fildes_varname
)) {
581 if ( VG_(clo_verbosity
) > 1 ) {
582 VG_(message
)( Vg_DebugMsg
,
583 "vfork kludge: found symbol %s at addr %p\n",
584 *names
, (void*) sym_avmas
.main
);
586 VG_(vfork_fildes_addr
) = (Int
*) sym_avmas
.main
;
587 vg_vfork_fildes_var_search
= False
;
593 /* It's not a full-scale redirect, but perhaps it is a load-notify
594 fn? Let the load-notify department see it. */
595 handle_maybe_load_notifier( newdi_soname
, *names
, sym_avmas
.main
);
598 if (check_ppcTOCs
&& GET_TOCPTR_AVMA(sym_avmas
) == 0) {
599 /* This platform uses toc pointers, but none could be found
600 for this symbol, so we can't safely redirect/wrap to it.
601 Just skip it; we'll make a second pass over the symbols in
602 the following loop, and complain at that point. */
606 HChar
*replaced_sopatt
= NULL
;
607 if (0 == VG_(strncmp
) (demangled_sopatt
,
608 VG_SO_SYN_PREFIX
, VG_SO_SYN_PREFIX_LEN
)) {
609 /* This is a redirection for handling lib so synonyms. If we
610 have a matching lib synonym, then replace the sopatt.
611 Otherwise, just ignore this redirection spec. */
613 /* Search for a matching synonym=newname*/
614 SizeT
const sopatt_syn_len
615 = VG_(strlen
)(demangled_sopatt
+VG_SO_SYN_PREFIX_LEN
);
616 HChar
const* last
= VG_(clo_soname_synonyms
);
618 while (last
!= NULL
&& *last
) {
619 HChar
const* first
= last
;
620 last
= advance_to_equal(first
);
622 if ((last
- first
) == sopatt_syn_len
623 && 0 == VG_(strncmp
)(demangled_sopatt
+VG_SO_SYN_PREFIX_LEN
,
626 // Found the demangle_sopatt synonym => replace it
628 last
= advance_to_comma(first
);
629 replaced_sopatt
= dinfo_zalloc("redir.rnnD.5",
631 VG_(strncpy
)(replaced_sopatt
, first
, last
- first
);
632 replaced_sopatt
[last
- first
] = '\0';
633 demangled_sopatt
= replaced_sopatt
;
637 last
= advance_to_comma(last
);
642 // If the user didn't set it then somalloc is special. We
643 // want to match public/global symbols that match the
644 // fnpatt everywhere.
645 if (replaced_sopatt
== NULL
646 && VG_(strcmp
) ( demangled_sopatt
, SO_SYN_MALLOC_NAME
) == 0)
648 replaced_sopatt
= dinfo_strdup("m_redir.rnnD.1", "*");
649 demangled_sopatt
= replaced_sopatt
;
653 // If we have not replaced the sopatt, then skip the redir.
654 if (replaced_sopatt
== NULL
)
658 spec
= dinfo_zalloc("redir.rnnD.1", sizeof(Spec
));
659 spec
->from_sopatt
= dinfo_strdup("redir.rnnD.2", demangled_sopatt
);
660 spec
->from_fnpatt
= dinfo_strdup("redir.rnnD.3", demangled_fnpatt
);
661 spec
->to_addr
= sym_avmas
.main
;
662 spec
->isWrap
= isWrap
;
663 spec
->isGlobal
= isGlobal
;
664 spec
->becTag
= becTag
;
665 spec
->becPrio
= becPrio
;
666 /* check we're not adding manifestly stupid destinations */
667 vg_assert(is_plausible_guest_addr(sym_avmas
.main
));
668 spec
->next
= specList
;
669 spec
->mark
= False
; /* not significant */
670 spec
->done
= False
; /* not significant */
672 /* The demangler is the owner of the demangled_sopatt memory,
673 unless it was replaced. In this case, we have to free the
674 replace_sopatt(==demangled_sopatt). We can free it,
675 because it was dinfo_strup-ed into spec->from_sopatt. */
676 if (replaced_sopatt
!= NULL
) {
677 vg_assert(demangled_sopatt
== replaced_sopatt
);
678 dinfo_free(replaced_sopatt
);
681 free_symname_array(names_init
, &twoslots
[0]);
683 if (dehacktivate_pthread_stack_cache_var_search
) {
684 VG_(message
)(Vg_DebugMsg
,
685 "WARNING: could not find symbol for var %s in %s\n",
686 pthread_stack_cache_actsize_varname
, pthread_soname
);
687 VG_(message
)(Vg_DebugMsg
,
688 "=> pthread stack cache cannot be disabled!\n");
690 #if defined(VGO_solaris)
691 if (vg_vfork_fildes_var_search
) {
692 VG_(message
)(Vg_DebugMsg
,
693 "WARNING: could not find symbol for var %s in %s\n",
694 vg_vfork_fildes_varname
, vg_preload_core_soname
);
695 VG_(message
)(Vg_DebugMsg
,
696 "=> posix_spawn() will not work correctly!\n");
701 for (i
= 0; i
< nsyms
; i
++) {
702 VG_(DebugInfo_syms_getidx
)( newdi
, i
, &sym_avmas
,
703 NULL
, &sym_name_pri
, &sym_names_sec
,
704 &isText
, NULL
, NULL
);
705 const HChar
* twoslots
[2];
706 const HChar
** names_init
=
707 alloc_symname_array(sym_name_pri
, sym_names_sec
, &twoslots
[0]);
709 for (names
= names_init
; *names
; names
++) {
711 && VG_(maybe_Z_demangle
)(
712 *names
, &demangled_sopatt
,
713 &demangled_fnpatt
, &isWrap
, NULL
, NULL
);
715 /* not a redirect. Ignore. */
717 if (GET_TOCPTR_AVMA(sym_avmas
) != 0)
718 /* has a valid toc pointer. Ignore. */
721 for (spec
= specList
; spec
; spec
= spec
->next
)
722 if (0 == VG_(strcmp
)(spec
->from_sopatt
, demangled_sopatt
)
723 && 0 == VG_(strcmp
)(spec
->from_fnpatt
, demangled_fnpatt
))
726 /* a redirect to some other copy of that symbol, which
727 does have a TOC value, already exists */
731 VG_(message
)(Vg_DebugMsg
,
732 "WARNING: no TOC ptr for redir/wrap to %s %s\n",
733 demangled_sopatt
, demangled_fnpatt
);
735 free_symname_array(names_init
, &twoslots
[0]);
739 /* Ok. Now specList holds the list of specs from the DebugInfo.
740 Build a new TopSpec, but don't add it to topSpecs yet. */
741 newts
= dinfo_zalloc("redir.rnnD.4", sizeof(TopSpec
));
742 newts
->next
= NULL
; /* not significant */
743 newts
->seginfo
= newdi
;
744 newts
->specs
= specList
;
745 newts
->mark
= False
; /* not significant */
747 /* We now need to augment the active set with the following partial
750 (1) actives formed by matching the new specs in specList against
751 all symbols currently listed in topSpecs
753 (2) actives formed by matching the new symbols in newdi against
754 all specs currently listed in topSpecs
756 (3) actives formed by matching the new symbols in newdi against
757 the new specs in specList
759 This is necessary in order to maintain the invariant that
760 Actives contains all bindings generated by matching ALL specs in
761 topSpecs against ALL symbols in topSpecs (that is, a cross
762 product of ALL known specs against ALL known symbols).
765 for (ts
= topSpecs
; ts
; ts
= ts
->next
) {
767 generate_and_add_actives( specList
, newts
,
772 for (ts
= topSpecs
; ts
; ts
= ts
->next
) {
773 generate_and_add_actives( ts
->specs
, ts
,
778 generate_and_add_actives( specList
, newts
,
781 /* Finally, add the new TopSpec. */
782 newts
->next
= topSpecs
;
785 if (VG_(clo_trace_redir
))
786 show_redir_state("after VG_(redir_notify_new_DebugInfo)");
788 /* Really finally (quite unrelated to all the above) check the
789 names in the module against any --require-text-symbol=
790 specifications we might have. */
791 handle_require_text_symbols(newdi
);
794 /* Add a new target for an indirect function. Adds a new redirection
795 for the indirection function with address old_from that redirects
796 the ordinary function with address new_from to the target address
797 of the original redirection. */
799 void VG_(redir_add_ifunc_target
)( Addr old_from
, Addr new_from
)
803 old
= VG_(OSetGen_Lookup
)(activeSet
, &old_from
);
805 vg_assert(old
->isIFunc
);
808 new.from_addr
= new_from
;
810 maybe_add_active (new);
812 if (VG_(clo_trace_redir
)) {
813 VG_(message
)( Vg_DebugMsg
,
814 "Adding redirect for indirect function "
815 "0x%lx from 0x%lx -> 0x%lx\n",
816 old_from
, new_from
, new.to_addr
);
820 /* Do one element of the basic cross product: add to the active set,
821 all matches resulting from comparing all the given specs against
822 all the symbols in the given seginfo. If a conflicting binding
823 would thereby arise, don't add it, but do complain. */
826 void generate_and_add_actives (
827 /* spec list and the owning TopSpec */
829 TopSpec
* parent_spec
,
830 /* seginfo and the owning TopSpec */
836 Bool anyMark
, isText
, isIFunc
, isGlobal
;
840 const HChar
* sym_name_pri
;
841 const HChar
** sym_names_sec
;
843 /* First figure out which of the specs match the seginfo's soname.
844 Also clear the 'done' bits, so that after the main loop below
845 tell which of the Specs really did get done. */
847 for (sp
= specs
; sp
; sp
= sp
->next
) {
849 const HChar
*soname
= VG_(DebugInfo_get_soname
)(di
);
851 /* When searching for global public symbols (like for the somalloc
852 synonym symbols), exclude the dynamic (runtime) linker as it is very
853 special. See https://bugs.kde.org/show_bug.cgi?id=355454 */
854 if ((VG_(strcmp
)(sp
->from_sopatt
, "*") == 0) &&
855 (sp
->isGlobal
== True
) &&
856 VG_(is_soname_ld_so
)(soname
)) {
861 sp
->mark
= VG_(string_match
)( sp
->from_sopatt
, soname
);
862 anyMark
= anyMark
|| sp
->mark
;
864 /* The symtab might be in a separate debuginfo file. Make sure the
865 debuginfo is fully loaded. */
866 if (sp
->mark
&& sp
->mandatory
)
870 /* shortcut: if none of the sonames match, there will be no bindings. */
874 /* Iterate outermost over the symbols in the seginfo, in the hope
875 of trashing the caches less. */
876 nsyms
= VG_(DebugInfo_syms_howmany
)( di
);
877 for (i
= 0; i
< nsyms
; i
++) {
878 VG_(DebugInfo_syms_getidx
)( di
, i
, &sym_avmas
,
879 NULL
, &sym_name_pri
, &sym_names_sec
,
880 &isText
, &isIFunc
, &isGlobal
);
881 const HChar
* twoslots
[2];
882 const HChar
** names_init
=
883 alloc_symname_array(sym_name_pri
, sym_names_sec
, &twoslots
[0]);
885 for (names
= names_init
; *names
; names
++) {
887 /* ignore data symbols */
891 for (sp
= specs
; sp
; sp
= sp
->next
) {
893 continue; /* soname doesn't match */
894 if (VG_(string_match
)( sp
->from_fnpatt
, *names
)
895 && (sp
->isGlobal
== False
|| isGlobal
== True
)) {
896 /* got a new binding. Add to collection. */
897 act
.from_addr
= sym_avmas
.main
;
898 act
.to_addr
= sp
->to_addr
;
899 act
.parent_spec
= parent_spec
;
900 act
.parent_sym
= parent_sym
;
901 act
.becTag
= sp
->becTag
;
902 act
.becPrio
= sp
->becPrio
;
903 act
.isWrap
= sp
->isWrap
;
904 act
.isIFunc
= isIFunc
;
906 maybe_add_active( act
);
908 /* If the function being wrapped has a local entry point
909 * redirect it to the global entry point. The redirection
910 * must save and setup r2 then setup r12 for the new function.
911 * On return, r2 must be restored. Local entry points used
912 * in PPC64 Little Endian.
914 if (GET_LOCAL_EP_AVMA(sym_avmas
) != 0) {
915 act
.from_addr
= GET_LOCAL_EP_AVMA(sym_avmas
);
916 maybe_add_active( act
);
920 } /* for (sp = specs; sp; sp = sp->next) */
922 } /* iterating over names[] */
923 free_symname_array(names_init
, &twoslots
[0]);
924 } /* for (i = 0; i < nsyms; i++) */
926 /* Now, finally, look for Specs which were marked to be done, but
927 didn't get matched. If any such are mandatory we must abort the
928 system at this point. */
929 for (sp
= specs
; sp
; sp
= sp
->next
) {
932 if (sp
->mark
&& (!sp
->done
) && sp
->mandatory
)
937 const HChar
* v
= "valgrind: ";
939 vg_assert(!sp
->done
);
940 vg_assert(sp
->mandatory
);
943 "%sFatal error at startup: a function redirection\n", v
);
945 "%swhich is mandatory for this platform-tool combination\n", v
);
947 "%scannot be set up. Details of the redirection are:\n", v
);
951 "%sA must-be-redirected function\n", v
);
953 "%swhose name matches the pattern: %s\n", v
, sp
->from_fnpatt
);
955 "%sin an object with soname matching: %s\n", v
, sp
->from_sopatt
);
957 "%swas not found whilst processing\n", v
);
959 "%ssymbols from the object with soname: %s\n",
960 v
, VG_(DebugInfo_get_soname
)(di
));
964 for (strp
= sp
->mandatory
; *strp
; strp
++)
971 "%sCannot continue -- exiting now. Sorry.\n", v
);
978 /* Add an act (passed by value; is copied here) and deal with
979 conflicting bindings. */
980 static void maybe_add_active ( Active act
)
982 const HChar
* what
= NULL
;
984 Bool add_act
= False
;
986 /* Complain and ignore manifestly bogus 'from' addresses.
988 Kludge: because this can get called befor the trampoline area (a
989 bunch of magic 'to' addresses) has its ownership changed from V
990 to C, we can't check the 'to' address similarly. Sigh.
992 amd64-linux hack: the vsysinfo pages appear to have no
994 ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0
995 so skip the check for them. */
996 if (!is_plausible_guest_addr(act
.from_addr
)
997 # if defined(VGP_amd64_linux)
998 && act
.from_addr
!= 0xFFFFFFFFFF600000ULL
999 && act
.from_addr
!= 0xFFFFFFFFFF600400ULL
1000 && act
.from_addr
!= 0xFFFFFFFFFF600800ULL
1003 what
= "redirection from-address is in non-executable area";
1007 old
= VG_(OSetGen_Lookup
)( activeSet
, &act
.from_addr
);
1009 /* Dodgy. Conflicting binding. */
1010 vg_assert(old
->from_addr
== act
.from_addr
);
1011 if (old
->to_addr
!= act
.to_addr
) {
1012 /* We've got a conflicting binding -- that is, from_addr is
1013 specified to redirect to two different destinations,
1014 old->to_addr and act.to_addr. If we can prove that they
1015 are behaviourally equivalent then that's no problem. So
1016 we can look at the behavioural eclass tags for both
1017 functions to see if that's so. If they are equal, and
1018 nonzero, then that's fine. But if not, we can't show they
1019 are equivalent, so we have to complain, and ignore the new
1021 vg_assert(old
->becTag
>= 0 && old
->becTag
<= 9999);
1022 vg_assert(old
->becPrio
>= 0 && old
->becPrio
<= 9);
1023 vg_assert(act
.becTag
>= 0 && act
.becTag
<= 9999);
1024 vg_assert(act
.becPrio
>= 0 && act
.becPrio
<= 9);
1025 if (old
->becTag
== 0)
1026 vg_assert(old
->becPrio
== 0);
1027 if (act
.becTag
== 0)
1028 vg_assert(act
.becPrio
== 0);
1030 if (old
->becTag
== 0 || act
.becTag
== 0 || old
->becTag
!= act
.becTag
) {
1031 /* We can't show that they are equivalent. Complain and
1033 what
= "new redirection conflicts with existing -- ignoring it";
1036 /* They have the same eclass tag. Use the priorities to
1037 resolve the ambiguity. */
1038 if (act
.becPrio
<= old
->becPrio
) {
1039 /* The new one doesn't have a higher priority, so just
1041 if (VG_(clo_verbosity
) > 2) {
1042 VG_(message
)(Vg_UserMsg
, "Ignoring %s redirection:\n",
1043 act
.becPrio
< old
->becPrio
? "lower priority"
1045 show_active( " old: ", old
);
1046 show_active( " new: ", &act
);
1049 /* The tricky case. The new one has a higher priority, so
1050 we need to get the old one out of the OSet and install
1051 this one in its place. */
1052 if (VG_(clo_verbosity
) > 1) {
1053 VG_(message
)(Vg_UserMsg
,
1054 "Preferring higher priority redirection:\n");
1055 show_active( " old: ", old
);
1056 show_active( " new: ", &act
);
1059 void* oldNd
= VG_(OSetGen_Remove
)( activeSet
, &act
.from_addr
);
1060 vg_assert(oldNd
== old
);
1061 VG_(OSetGen_FreeNode
)( activeSet
, old
);
1065 /* This appears to be a duplicate of an existing binding.
1066 Safe(ish) -- ignore. */
1067 /* XXXXXXXXXXX COMPLAIN if new and old parents differ */
1071 /* There's no previous binding for this from_addr, so we must
1072 add 'act' to the active set. */
1076 /* So, finally, actually add it. */
1078 Active
* a
= VG_(OSetGen_AllocNode
)(activeSet
, sizeof(Active
));
1081 VG_(OSetGen_Insert
)(activeSet
, a
);
1082 /* Now that a new from->to redirection is in force, we need to
1083 get rid of any translations intersecting 'from' in order that
1084 they get redirected to 'to'. So discard them. Just for
1085 paranoia (but, I believe, unnecessarily), discard 'to' as
1087 VG_(discard_translations
)( act
.from_addr
, 1,
1088 "redir_new_DebugInfo(from_addr)");
1089 VG_(discard_translations
)( act
.to_addr
, 1,
1090 "redir_new_DebugInfo(to_addr)");
1091 if (VG_(clo_verbosity
) > 2) {
1092 VG_(message
)(Vg_UserMsg
, "Adding active redirection:\n");
1093 show_active( " new: ", &act
);
1100 vg_assert(!add_act
);
1101 if (VG_(clo_verbosity
) > 1) {
1102 VG_(message
)(Vg_UserMsg
, "WARNING: %s\n", what
);
1104 show_active( " old: ", old
);
1106 show_active( " new: ", &act
);
1111 /* Notify m_redir of the deletion of a DebugInfo. This is relatively
1112 simple -- just get rid of all actives derived from it, and free up
1113 the associated list elements. */
1115 void VG_(redir_notify_delete_DebugInfo
)( const DebugInfo
* delsi
)
1128 /* Search for it, and make tsPrev point to the previous entry, if
1133 if (ts
== NULL
) break;
1134 if (ts
->seginfo
== delsi
) break;
1139 vg_assert(ts
); /* else we don't have the deleted DebugInfo */
1140 vg_assert(ts
->seginfo
== delsi
);
1142 /* Traverse the actives, copying the addresses of those we intend
1143 to delete into tmpSet. */
1144 tmpSet
= VG_(OSetWord_Create
)(dinfo_zalloc
, "redir.rndD.1", dinfo_free
);
1148 VG_(OSetGen_ResetIter
)( activeSet
);
1149 while ( (act
= VG_(OSetGen_Next
)(activeSet
)) ) {
1150 delMe
= act
->parent_spec
!= NULL
1151 && act
->parent_sym
!= NULL
1152 && act
->parent_spec
->seginfo
!= NULL
1153 && act
->parent_sym
->seginfo
!= NULL
1154 && (act
->parent_spec
->mark
|| act
->parent_sym
->mark
);
1156 /* While we're at it, a bit of paranoia: delete any actives
1157 which don't have both feet in valid client executable areas.
1158 But don't delete hardwired-at-startup ones; these are denoted
1159 by having parent_spec or parent_sym being NULL. */
1161 && act
->parent_spec
!= NULL
1162 && act
->parent_sym
!= NULL
) {
1163 if (!is_plausible_guest_addr(act
->from_addr
))
1165 if (!is_plausible_guest_addr(act
->to_addr
))
1170 VG_(OSetWord_Insert
)( tmpSet
, act
->from_addr
);
1171 /* While we have our hands on both the 'from' and 'to'
1172 of this Active, do paranoid stuff with tt/tc. */
1173 VG_(discard_translations
)( act
->from_addr
, 1,
1174 "redir_del_DebugInfo(from_addr)");
1175 VG_(discard_translations
)( act
->to_addr
, 1,
1176 "redir_del_DebugInfo(to_addr)");
1180 /* Now traverse tmpSet, deleting corresponding elements in activeSet. */
1181 VG_(OSetWord_ResetIter
)( tmpSet
);
1182 while ( VG_(OSetWord_Next
)(tmpSet
, &addr
) ) {
1183 act
= VG_(OSetGen_Remove
)( activeSet
, &addr
);
1185 VG_(OSetGen_FreeNode
)( activeSet
, act
);
1188 VG_(OSetWord_Destroy
)( tmpSet
);
1190 /* The Actives set is now cleaned up. Free up this TopSpec and
1191 everything hanging off it. */
1192 for (sp
= ts
->specs
; sp
; sp
= sp_next
) {
1193 if (sp
->from_sopatt
) dinfo_free(sp
->from_sopatt
);
1194 if (sp
->from_fnpatt
) dinfo_free(sp
->from_fnpatt
);
1199 if (tsPrev
== NULL
) {
1201 topSpecs
= ts
->next
;
1203 tsPrev
->next
= ts
->next
;
1207 if (VG_(clo_trace_redir
))
1208 show_redir_state("after VG_(redir_notify_delete_DebugInfo)");
1212 /*------------------------------------------------------------*/
1213 /*--- QUERIES (really the whole point of this module) ---*/
1214 /*------------------------------------------------------------*/
1216 /* This is the crucial redirection function. It answers the question:
1217 should this code address be redirected somewhere else? It's used
1218 just before translating a basic block. */
1219 Addr
VG_(redir_do_lookup
) ( Addr orig
, Bool
* isWrap
)
1221 Active
* r
= VG_(OSetGen_Lookup
)(activeSet
, &orig
);
1223 if (isWrap
) *isWrap
= False
;
1227 vg_assert(r
->to_addr
!= 0);
1229 *isWrap
= r
->isWrap
|| r
->isIFunc
;
1231 vg_assert(iFuncWrapper
);
1232 return iFuncWrapper
;
1237 /* Does the soname represent a dynamic (runtime) linker?
1238 Considers various VG_U_LD* entries from pub_tool_redir.h. */
1239 Bool
VG_(is_soname_ld_so
) (const HChar
*soname
)
1241 # if defined(VGO_linux)
1242 if (VG_STREQ(soname
, VG_U_LD_LINUX_SO_3
)) return True
;
1243 if (VG_STREQ(soname
, VG_U_LD_LINUX_SO_2
)) return True
;
1244 if (VG_STREQ(soname
, VG_U_LD_LINUX_X86_64_SO_2
)) return True
;
1245 if (VG_STREQ(soname
, VG_U_LD64_SO_1
)) return True
;
1246 if (VG_STREQ(soname
, VG_U_LD64_SO_2
)) return True
;
1247 if (VG_STREQ(soname
, VG_U_LD_SO_1
)) return True
;
1248 if (VG_STREQ(soname
, VG_U_LD_LINUX_AARCH64_SO_1
)) return True
;
1249 if (VG_STREQ(soname
, VG_U_LD_LINUX_ARMHF_SO_3
)) return True
;
1250 if (VG_STREQ(soname
, VG_U_LD_LINUX_MIPSN8_S0_1
)) return True
;
1251 # elif defined(VGO_freebsd)
1252 if (VG_STREQ(soname
, VG_U_LD_ELF_SO_1
)) return True
;
1253 if (VG_STREQ(soname
, VG_U_LD_ELF32_SO_1
)) return True
;
1254 # elif defined(VGO_darwin)
1255 if (VG_STREQ(soname
, VG_U_DYLD
)) return True
;
1256 # elif defined(VGO_solaris)
1257 if (VG_STREQ(soname
, VG_U_LD_SO_1
)) return True
;
1259 # error "Unsupported OS"
1265 /*------------------------------------------------------------*/
1266 /*--- INITIALISATION ---*/
1267 /*------------------------------------------------------------*/
1269 /* Add a never-delete-me Active. */
1271 __attribute__((unused
)) /* only used on amd64 */
1272 static void add_hardwired_active ( Addr from
, Addr to
)
1275 act
.from_addr
= from
;
1277 act
.parent_spec
= NULL
;
1278 act
.parent_sym
= NULL
;
1279 act
.becTag
= 0; /* "not equivalent to any other fn" */
1280 act
.becPrio
= 0; /* mandatory when becTag == 0 */
1282 act
.isIFunc
= False
;
1283 maybe_add_active( act
);
1287 /* Add a never-delete-me Spec. This is a bit of a kludge. On the
1288 assumption that this is called only at startup, only handle the
1289 case where topSpecs is completely empty, or if it isn't, it has
1290 just one entry and that is the one with NULL seginfo -- that is the
1291 entry that holds these initial specs. */
1293 __attribute__((unused
)) /* not used on all platforms */
1294 static void add_hardwired_spec (const HChar
* sopatt
, const HChar
* fnpatt
,
1296 const HChar
** mandatory
)
1298 Spec
* spec
= dinfo_zalloc("redir.ahs.1", sizeof(Spec
));
1300 if (topSpecs
== NULL
) {
1301 topSpecs
= dinfo_zalloc("redir.ahs.2", sizeof(TopSpec
));
1302 /* symtab_zalloc sets all fields to zero */
1305 vg_assert(topSpecs
!= NULL
);
1306 vg_assert(topSpecs
->next
== NULL
);
1307 vg_assert(topSpecs
->seginfo
== NULL
);
1309 /* Note, that these CONST_CAST will not cause a problem, in the sense
1310 that VG_(redir_notify_delete_DebugInfo) will delete them. The reason
1311 is that the TopSpec here has seginfo == NULL and such a TopSpec will
1312 never be freed. See the asserts at the beginning of said function. */
1313 spec
->from_sopatt
= CONST_CAST(HChar
*,sopatt
);
1314 spec
->from_fnpatt
= CONST_CAST(HChar
*,fnpatt
);
1315 spec
->to_addr
= to_addr
;
1316 spec
->isWrap
= False
;
1317 spec
->isGlobal
= False
;
1318 spec
->mandatory
= mandatory
;
1319 /* VARIABLE PARTS */
1320 spec
->mark
= False
; /* not significant */
1321 spec
->done
= False
; /* not significant */
1323 spec
->next
= topSpecs
->specs
;
1324 topSpecs
->specs
= spec
;
1328 __attribute__((unused
)) /* not used on all platforms */
1329 static const HChar
* complain_about_stripped_glibc_ldso
[]
1330 = { "Possible fixes: (1, short term): install glibc's debuginfo",
1331 "package on this machine. (2, longer term): ask the packagers",
1332 "for your Linux distribution to please in future ship a non-",
1333 "stripped ld.so (or whatever the dynamic linker .so is called)",
1334 "that exports the above-named function using the standard",
1335 "calling conventions for this platform. The package you need",
1336 "to install for fix (1) is called",
1338 " On Debian, Ubuntu: libc6-dbg",
1339 " On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo",
1341 "Note that if you are debugging a 32 bit process on a",
1342 "64 bit system, you will need a corresponding 32 bit debuginfo",
1343 "package (e.g. libc6-dbg:i386).",
1348 /* Initialise the redir system, and create the initial Spec list and
1349 for amd64-linux a couple of permanent active mappings. The initial
1350 Specs are not converted into Actives yet, on the (checked)
1351 assumption that no DebugInfos have so far been created, and so when
1352 they are created, that will happen. */
1354 void VG_(redir_initialise
) ( void )
1356 // Assert that there are no DebugInfos so far
1357 vg_assert( VG_(next_DebugInfo
)(NULL
) == NULL
);
1359 // Initialise active mapping.
1360 activeSet
= VG_(OSetGen_Create
)(offsetof(Active
, from_addr
),
1361 NULL
, // Use fast comparison
1366 // The rest of this function just adds initial Specs.
1368 # if defined(VGP_x86_linux)
1369 /* If we're using memcheck, use this intercept right from the
1370 start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */
1371 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1372 const HChar
** mandatory
;
1373 # ifndef GLIBC_MANDATORY_INDEX_AND_STRLEN_REDIRECT
1376 /* for glibc-2.12 and later, this is mandatory - can't sanely
1377 continue without it */
1378 mandatory
= complain_about_stripped_glibc_ldso
;
1381 "ld-linux.so.2", "index",
1382 (Addr
)&VG_(x86_linux_REDIR_FOR_index
), mandatory
);
1384 "ld-linux.so.2", "strlen",
1385 (Addr
)&VG_(x86_linux_REDIR_FOR_strlen
), mandatory
);
1388 # elif defined(VGP_amd64_linux)
1389 /* Redirect vsyscalls to local versions */
1390 add_hardwired_active(
1391 0xFFFFFFFFFF600000ULL
,
1392 (Addr
)&VG_(amd64_linux_REDIR_FOR_vgettimeofday
)
1394 add_hardwired_active(
1395 0xFFFFFFFFFF600400ULL
,
1396 (Addr
)&VG_(amd64_linux_REDIR_FOR_vtime
)
1398 add_hardwired_active(
1399 0xFFFFFFFFFF600800ULL
,
1400 (Addr
)&VG_(amd64_linux_REDIR_FOR_vgetcpu
)
1403 /* If we're using memcheck, use these intercepts right from
1404 the start, otherwise ld.so makes a lot of noise. */
1405 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1408 "ld-linux-x86-64.so.2", "index",
1409 (Addr
)&VG_(amd64_linux_REDIR_FOR_index
), NULL
);
1411 "ld-linux-x86-64.so.2", "strlen",
1412 (Addr
)&VG_(amd64_linux_REDIR_FOR_strlen
),
1413 # ifndef GLIBC_MANDATORY_STRLEN_REDIRECT
1416 /* for glibc-2.10 and later, this is mandatory - can't sanely
1417 continue without it */
1418 complain_about_stripped_glibc_ldso
1422 "ld-linux-x86-64.so.2", "strcmp",
1423 (Addr
)&VG_(amd64_linux_REDIR_FOR_strcmp
),
1424 # ifndef GLIBC_MANDATORY_STRLEN_REDIRECT
1427 complain_about_stripped_glibc_ldso
1432 # elif defined(VGP_ppc32_linux)
1433 /* If we're using memcheck, use these intercepts right from
1434 the start, otherwise ld.so makes a lot of noise. */
1435 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1437 /* this is mandatory - can't sanely continue without it */
1439 "ld.so.1", "strlen",
1440 (Addr
)&VG_(ppc32_linux_REDIR_FOR_strlen
),
1441 complain_about_stripped_glibc_ldso
1444 "ld.so.1", "strcmp",
1445 (Addr
)&VG_(ppc32_linux_REDIR_FOR_strcmp
),
1446 NULL
/* not mandatory - so why bother at all? */
1447 /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
1451 (Addr
)&VG_(ppc32_linux_REDIR_FOR_strchr
),
1452 NULL
/* not mandatory - so why bother at all? */
1453 /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
1457 # elif defined(VGP_ppc64be_linux)
1458 /* If we're using memcheck, use these intercepts right from
1459 the start, otherwise ld.so makes a lot of noise. */
1460 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1462 /* this is mandatory - can't sanely continue without it */
1464 "ld64.so.1", "strlen",
1465 (Addr
)VG_(fnptr_to_fnentry
)( &VG_(ppc64_linux_REDIR_FOR_strlen
) ),
1466 complain_about_stripped_glibc_ldso
1470 "ld64.so.1", "index",
1471 (Addr
)VG_(fnptr_to_fnentry
)( &VG_(ppc64_linux_REDIR_FOR_strchr
) ),
1472 NULL
/* not mandatory - so why bother at all? */
1473 /* glibc-2.5 (FC6, ppc64) seems fine without it */
1477 # elif defined(VGP_ppc64le_linux)
1478 /* If we're using memcheck, use these intercepts right from
1479 * the start, otherwise ld.so makes a lot of noise.
1481 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1483 /* this is mandatory - can't sanely continue without it */
1485 "ld64.so.2", "strlen",
1486 (Addr
)&VG_(ppc64_linux_REDIR_FOR_strlen
),
1487 complain_about_stripped_glibc_ldso
1491 "ld64.so.2", "index",
1492 (Addr
)&VG_(ppc64_linux_REDIR_FOR_strchr
),
1493 NULL
/* not mandatory - so why bother at all? */
1494 /* glibc-2.5 (FC6, ppc64) seems fine without it */
1498 # elif defined(VGP_arm_linux)
1499 /* If we're using memcheck, use these intercepts right from the
1500 start, otherwise ld.so makes a lot of noise. In most ARM-linux
1501 distros, ld.so's soname is ld-linux.so.3, but Ubuntu 14.04 on
1502 Odroid uses ld-linux-armhf.so.3 for some reason. */
1503 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1506 "ld-linux.so.3", "strlen",
1507 (Addr
)&VG_(arm_linux_REDIR_FOR_strlen
),
1508 complain_about_stripped_glibc_ldso
1511 "ld-linux-armhf.so.3", "strlen",
1512 (Addr
)&VG_(arm_linux_REDIR_FOR_strlen
),
1513 complain_about_stripped_glibc_ldso
1517 "ld-linux.so.3", "memcpy",
1518 (Addr
)&VG_(arm_linux_REDIR_FOR_memcpy
),
1519 complain_about_stripped_glibc_ldso
1522 "ld-linux-armhf.so.3", "memcpy",
1523 (Addr
)&VG_(arm_linux_REDIR_FOR_memcpy
),
1524 complain_about_stripped_glibc_ldso
1528 "ld-linux.so.3", "strcmp",
1529 (Addr
)&VG_(arm_linux_REDIR_FOR_strcmp
),
1530 complain_about_stripped_glibc_ldso
1533 "ld-linux-armhf.so.3", "strcmp",
1534 (Addr
)&VG_(arm_linux_REDIR_FOR_strcmp
),
1535 complain_about_stripped_glibc_ldso
1539 "ld-linux.so.3", "index",
1540 (Addr
)&VG_(arm_linux_REDIR_FOR_index
),
1541 complain_about_stripped_glibc_ldso
1544 "ld-linux-armhf.so.3", "index",
1545 (Addr
)&VG_(arm_linux_REDIR_FOR_index
),
1546 complain_about_stripped_glibc_ldso
1550 # elif defined(VGP_arm64_linux)
1551 /* If we're using memcheck, use these intercepts right from
1552 the start, otherwise ld.so makes a lot of noise. */
1553 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1555 "ld-linux-aarch64.so.1", "strlen",
1556 (Addr
)&VG_(arm64_linux_REDIR_FOR_strlen
),
1557 complain_about_stripped_glibc_ldso
1560 "ld-linux-aarch64.so.1", "index",
1561 (Addr
)&VG_(arm64_linux_REDIR_FOR_index
),
1565 "ld-linux-aarch64.so.1", "strcmp",
1566 (Addr
)&VG_(arm64_linux_REDIR_FOR_strcmp
),
1569 # if defined(VGPV_arm64_linux_android)
1571 "NONE", "__dl_strlen", // in /system/bin/linker64
1572 (Addr
)&VG_(arm64_linux_REDIR_FOR_strlen
),
1578 # elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) || defined(VGP_arm64_freebsd)
1579 /* XXX do something real if needed */
1580 # elif defined(VGP_x86_darwin)
1581 /* If we're using memcheck, use these intercepts right from
1582 the start, otherwise dyld makes a lot of noise. */
1583 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1584 add_hardwired_spec("dyld", "strcmp",
1585 (Addr
)&VG_(x86_darwin_REDIR_FOR_strcmp
), NULL
);
1586 add_hardwired_spec("dyld", "strlen",
1587 (Addr
)&VG_(x86_darwin_REDIR_FOR_strlen
), NULL
);
1588 add_hardwired_spec("dyld", "strcat",
1589 (Addr
)&VG_(x86_darwin_REDIR_FOR_strcat
), NULL
);
1590 add_hardwired_spec("dyld", "strcpy",
1591 (Addr
)&VG_(x86_darwin_REDIR_FOR_strcpy
), NULL
);
1592 add_hardwired_spec("dyld", "strlcat",
1593 (Addr
)&VG_(x86_darwin_REDIR_FOR_strlcat
), NULL
);
1596 # elif defined(VGP_amd64_darwin)
1597 /* If we're using memcheck, use these intercepts right from
1598 the start, otherwise dyld makes a lot of noise. */
1599 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1600 add_hardwired_spec("dyld", "strcmp",
1601 (Addr
)&VG_(amd64_darwin_REDIR_FOR_strcmp
), NULL
);
1602 add_hardwired_spec("dyld", "strlen",
1603 (Addr
)&VG_(amd64_darwin_REDIR_FOR_strlen
), NULL
);
1604 add_hardwired_spec("dyld", "strcat",
1605 (Addr
)&VG_(amd64_darwin_REDIR_FOR_strcat
), NULL
);
1606 add_hardwired_spec("dyld", "strcpy",
1607 (Addr
)&VG_(amd64_darwin_REDIR_FOR_strcpy
), NULL
);
1608 add_hardwired_spec("dyld", "strlcat",
1609 (Addr
)&VG_(amd64_darwin_REDIR_FOR_strlcat
), NULL
);
1610 // DDD: #warning fixme rdar://6166275
1611 add_hardwired_spec("dyld", "arc4random",
1612 (Addr
)&VG_(amd64_darwin_REDIR_FOR_arc4random
), NULL
);
1613 # if DARWIN_VERS == DARWIN_10_9
1614 add_hardwired_spec("dyld", "strchr",
1615 (Addr
)&VG_(amd64_darwin_REDIR_FOR_strchr
), NULL
);
1619 # elif defined(VGP_s390x_linux)
1620 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1621 // added in rsponse to BZ 327943
1622 add_hardwired_spec("ld64.so.1", "index",
1623 (Addr
)&VG_(s390x_linux_REDIR_FOR_index
),
1624 complain_about_stripped_glibc_ldso
);
1627 # elif defined(VGP_mips32_linux)
1628 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1629 /* this is mandatory - can't sanely continue without it */
1631 "ld.so.1", "strlen",
1632 (Addr
)&VG_(mips32_linux_REDIR_FOR_strlen
),
1633 complain_about_stripped_glibc_ldso
1637 (Addr
)&VG_(mips32_linux_REDIR_FOR_index
),
1638 complain_about_stripped_glibc_ldso
1640 # if defined(VGPV_mips32_linux_android)
1642 "NONE", "__dl_strlen",
1643 (Addr
)&VG_(mips32_linux_REDIR_FOR_strlen
),
1649 # elif defined(VGP_mips64_linux)
1650 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1651 /* this is mandatory - can't sanely continue without it */
1653 "ld.so.1", "strlen",
1654 (Addr
)&VG_(mips64_linux_REDIR_FOR_strlen
),
1655 complain_about_stripped_glibc_ldso
1659 (Addr
)&VG_(mips64_linux_REDIR_FOR_index
),
1660 complain_about_stripped_glibc_ldso
1662 # if defined(VGABI_64)
1664 "ld-linux-mipsn8.so.1", "strlen",
1665 (Addr
)&VG_(mips64_linux_REDIR_FOR_strlen
),
1666 complain_about_stripped_glibc_ldso
1669 "ld-linux-mipsn8.so.1", "index",
1670 (Addr
)&VG_(mips64_linux_REDIR_FOR_index
),
1671 complain_about_stripped_glibc_ldso
1673 # elif defined(VGABI_N32)
1675 "ld.so.1", "strchr",
1676 (Addr
)&VG_(mips64_linux_REDIR_FOR_index
),
1677 complain_about_stripped_glibc_ldso
1680 # error unknown mips64 ABI
1684 # elif defined(VGP_nanomips_linux)
1685 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1688 "ld.so.1", "strlen",
1689 (Addr
)&VG_(nanomips_linux_REDIR_FOR_strlen
),
1690 complain_about_stripped_glibc_ldso
1694 (Addr
)&VG_(nanomips_linux_REDIR_FOR_index
),
1695 complain_about_stripped_glibc_ldso
1699 # elif defined(VGP_x86_solaris)
1700 /* If we're using memcheck, use these intercepts right from
1701 the start, otherwise ld.so makes a lot of noise. */
1702 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1703 add_hardwired_spec("/lib/ld.so.1", "strcmp",
1704 (Addr
)&VG_(x86_solaris_REDIR_FOR_strcmp
), NULL
);
1706 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1707 add_hardwired_spec("/lib/ld.so.1", "strlen",
1708 (Addr
)&VG_(x86_solaris_REDIR_FOR_strlen
), NULL
);
1711 # elif defined(VGP_amd64_solaris)
1712 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1713 add_hardwired_spec("/lib/amd64/ld.so.1", "strcpy",
1714 (Addr
)&VG_(amd64_solaris_REDIR_FOR_strcpy
), NULL
);
1716 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1717 add_hardwired_spec("/lib/amd64/ld.so.1", "strncpy",
1718 (Addr
)&VG_(amd64_solaris_REDIR_FOR_strncpy
), NULL
);
1720 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1721 add_hardwired_spec("/lib/amd64/ld.so.1", "strcmp",
1722 (Addr
)&VG_(amd64_solaris_REDIR_FOR_strcmp
), NULL
);
1724 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1725 add_hardwired_spec("/lib/amd64/ld.so.1", "strcat",
1726 (Addr
)&VG_(amd64_solaris_REDIR_FOR_strcat
), NULL
);
1728 if (0==VG_(strcmp
)("Memcheck", VG_(details
).name
)) {
1729 add_hardwired_spec("/lib/amd64/ld.so.1", "strlen",
1730 (Addr
)&VG_(amd64_solaris_REDIR_FOR_strlen
), NULL
);
1734 # error Unknown platform
1737 if (VG_(clo_trace_redir
))
1738 show_redir_state("after VG_(redir_initialise)");
1742 /*------------------------------------------------------------*/
1743 /*--- MISC HELPERS ---*/
1744 /*------------------------------------------------------------*/
1746 static void* dinfo_zalloc(const HChar
* ec
, SizeT n
) {
1749 p
= VG_(arena_malloc
)(VG_AR_DINFO
, ec
, n
);
1750 VG_(memset
)(p
, 0, n
);
1754 static void dinfo_free(void* p
) {
1756 return VG_(arena_free
)(VG_AR_DINFO
, p
);
1759 static HChar
* dinfo_strdup(const HChar
* ec
, const HChar
* str
)
1761 return VG_(arena_strdup
)(VG_AR_DINFO
, ec
, str
);
1764 /* Really this should be merged with translations_allowable_from_seg
1766 static Bool
is_plausible_guest_addr(Addr a
)
1768 NSegment
const* seg
= VG_(am_find_nsegment
)(a
);
1770 && (seg
->kind
== SkAnonC
|| seg
->kind
== SkFileC
||
1771 seg
->kind
== SkShmC
)
1772 && (seg
->hasX
|| seg
->hasR
); /* crude x86-specific hack */
1776 /*------------------------------------------------------------*/
1777 /*--- NOTIFY-ON-LOAD FUNCTIONS ---*/
1778 /*------------------------------------------------------------*/
1781 void handle_maybe_load_notifier( const HChar
* soname
,
1782 const HChar
* symbol
, Addr addr
)
1784 # if defined(VGP_x86_linux)
1785 /* x86-linux only: if we see _dl_sysinfo_int80, note its address.
1786 See comment on declaration of VG_(client__dl_sysinfo_int80) for
1787 the reason. As far as I can tell, the relevant symbol is always
1788 in object with soname "ld-linux.so.2". */
1789 if (symbol
&& symbol
[0] == '_'
1790 && 0 == VG_(strcmp
)(symbol
, "_dl_sysinfo_int80")
1791 && 0 == VG_(strcmp
)(soname
, "ld-linux.so.2")) {
1792 if (VG_(client__dl_sysinfo_int80
) == 0)
1793 VG_(client__dl_sysinfo_int80
) = addr
;
1797 /* Normal load-notifier handling after here. First, ignore all
1798 symbols lacking the right prefix. */
1799 vg_assert(symbol
); // assert rather than segfault if it is NULL
1800 if (0 != VG_(strncmp
)(symbol
, VG_NOTIFY_ON_LOAD_PREFIX
,
1801 VG_NOTIFY_ON_LOAD_PREFIX_LEN
))
1802 /* Doesn't have the right prefix */
1805 if (VG_(strcmp
)(symbol
, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres
))) == 0)
1806 VG_(client_freeres_wrapper
) = addr
;
1808 if (VG_(strcmp
)(symbol
, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper
))) == 0)
1809 iFuncWrapper
= addr
;
1811 vg_assert2(0, "unrecognised load notification function: %s", symbol
);
1815 /*------------------------------------------------------------*/
1816 /*--- REQUIRE-TEXT-SYMBOL HANDLING ---*/
1817 /*------------------------------------------------------------*/
1819 /* In short: check that the currently-being-loaded object has text
1820 symbols that satisfy any --require-text-symbol= specifications that
1821 apply to it, and abort the run with an error message if not.
1823 static void handle_require_text_symbols ( DebugInfo
* di
)
1825 /* First thing to do is figure out which, if any,
1826 --require-text-symbol specification strings apply to this
1827 object. Most likely none do, since it is not expected to
1828 frequently be used. Work through the list of specs and
1829 accumulate in fnpatts[] the fn patterns that pertain to this
1831 XArray
*fnpatts
= VG_(newXA
)( VG_(malloc
), "m_redir.hrts.5",
1832 VG_(free
), sizeof(HChar
*) );
1835 const HChar
* di_soname
= VG_(DebugInfo_get_soname
)(di
);
1836 vg_assert(di_soname
); // must be present
1838 for (i
= 0; i
< VG_(sizeXA
)(VG_(clo_req_tsyms
)); i
++) {
1839 const HChar
* clo_spec
= *(HChar
**) VG_(indexXA
)(VG_(clo_req_tsyms
), i
);
1840 vg_assert(clo_spec
&& VG_(strlen
)(clo_spec
) >= 4);
1841 // clone the spec, so we can stick a zero at the end of the sopatt
1842 HChar
*spec
= VG_(strdup
)("m_redir.hrts.1", clo_spec
);
1843 HChar sep
= spec
[0];
1844 HChar
* sopatt
= &spec
[1];
1845 HChar
* fnpatt
= VG_(strchr
)(sopatt
, sep
);
1846 // the initial check at clo processing in time in m_main
1847 // should ensure this.
1848 vg_assert(fnpatt
&& *fnpatt
== sep
);
1851 if (VG_(string_match
)(sopatt
, di_soname
)) {
1852 HChar
*pattern
= VG_(strdup
)("m_redir.hrts.2", fnpatt
);
1853 VG_(addToXA
)(fnpatts
, &pattern
);
1858 if (VG_(sizeXA
)(fnpatts
) == 0) {
1859 VG_(deleteXA
)(fnpatts
);
1860 return; /* no applicable spec strings */
1863 /* So finally, fnpatts contains the set of
1864 (patterns for) text symbol names that must be found in this
1865 object, in order to continue. That is, we must find at least
1866 one text symbol name that matches each pattern, else we must
1869 if (0) VG_(printf
)("for %s\n", di_soname
);
1870 for (i
= 0; i
< VG_(sizeXA
)(fnpatts
); i
++)
1871 if (0) VG_(printf
)(" fnpatt: %s\n",
1872 *(HChar
**) VG_(indexXA
)(fnpatts
, i
));
1874 /* For each spec, look through the syms to find one that matches.
1875 This isn't terribly efficient but it happens rarely, so no big
1877 for (i
= 0; i
< VG_(sizeXA
)(fnpatts
); i
++) {
1879 const HChar
* fnpatt
= *(HChar
**) VG_(indexXA
)(fnpatts
, i
);
1880 Int nsyms
= VG_(DebugInfo_syms_howmany
)(di
);
1881 for (j
= 0; j
< nsyms
; j
++) {
1882 Bool isText
= False
;
1883 const HChar
* sym_name_pri
= NULL
;
1884 const HChar
** sym_names_sec
= NULL
;
1885 VG_(DebugInfo_syms_getidx
)( di
, j
, NULL
,
1886 NULL
, &sym_name_pri
, &sym_names_sec
,
1887 &isText
, NULL
, NULL
);
1888 const HChar
* twoslots
[2];
1889 const HChar
** names_init
=
1890 alloc_symname_array(sym_name_pri
, sym_names_sec
, &twoslots
[0]);
1891 const HChar
** names
;
1892 for (names
= names_init
; *names
; names
++) {
1893 /* ignore data symbols */
1894 if (0) VG_(printf
)("QQQ %s\n", *names
);
1895 vg_assert(sym_name_pri
);
1898 if (VG_(string_match
)(fnpatt
, *names
)) {
1903 free_symname_array(names_init
, &twoslots
[0]);
1909 const HChar
* v
= "valgrind: ";
1912 "%sFatal error at when loading library with soname\n", v
);
1914 "%s %s\n", v
, di_soname
);
1916 "%sCannot find any text symbol with a name "
1917 "that matches the pattern\n", v
);
1918 VG_(printf
)("%s %s\n", v
, fnpatt
);
1919 VG_(printf
)("%sas required by a --require-text-symbol= "
1920 "specification.\n", v
);
1923 "%sCannot continue -- exiting now.\n", v
);
1929 /* All required specs were found. Just free memory and return. */
1930 for (i
= 0; i
< VG_(sizeXA
)(fnpatts
); i
++)
1931 VG_(free
)(*(HChar
**) VG_(indexXA
)(fnpatts
, i
));
1932 VG_(deleteXA
)(fnpatts
);
1936 /*------------------------------------------------------------*/
1937 /*--- SANITY/DEBUG ---*/
1938 /*------------------------------------------------------------*/
1940 static void show_spec ( const HChar
* left
, const Spec
* spec
)
1942 VG_(message
)( Vg_DebugMsg
,
1943 "%s%-25s %-30s %s%s-> (%04d.%d) 0x%08lx\n",
1945 spec
->from_sopatt
, spec
->from_fnpatt
,
1946 spec
->isWrap
? "W" : "R",
1947 spec
->isGlobal
? "G" : "L",
1948 spec
->becTag
, spec
->becPrio
,
1952 static void show_active ( const HChar
* left
, const Active
* act
)
1957 DiEpoch ep
= VG_(current_DiEpoch
)();
1958 ok
= VG_(get_fnname_w_offset
)(ep
, act
->from_addr
, &buf
);
1959 if (!ok
) buf
= "???";
1961 HChar name1
[VG_(strlen
)(buf
) + 1];
1962 VG_(strcpy
)(name1
, buf
);
1965 ok
= VG_(get_fnname_w_offset
)(ep
, act
->to_addr
, &name2
);
1966 if (!ok
) name2
= "???";
1968 VG_(message
)(Vg_DebugMsg
, "%s0x%08lx (%-20s) %s-> (%04d.%d) 0x%08lx %s\n",
1970 act
->from_addr
, name1
,
1971 act
->isWrap
? "W" : "R",
1972 act
->becTag
, act
->becPrio
,
1973 act
->to_addr
, name2
);
1976 static void show_redir_state ( const HChar
* who
)
1981 VG_(message
)(Vg_DebugMsg
, "<<\n");
1982 VG_(message
)(Vg_DebugMsg
, " ------ REDIR STATE %s ------\n", who
);
1983 for (ts
= topSpecs
; ts
; ts
= ts
->next
) {
1985 VG_(message
)(Vg_DebugMsg
,
1986 " TOPSPECS of soname %s filename %s\n",
1987 VG_(DebugInfo_get_soname
)(ts
->seginfo
),
1988 VG_(DebugInfo_get_filename
)(ts
->seginfo
));
1990 VG_(message
)(Vg_DebugMsg
,
1991 " TOPSPECS of soname (hardwired)\n");
1993 for (sp
= ts
->specs
; sp
; sp
= sp
->next
)
1996 VG_(message
)(Vg_DebugMsg
, " ------ ACTIVE ------\n");
1997 VG_(OSetGen_ResetIter
)( activeSet
);
1998 while ( (act
= VG_(OSetGen_Next
)(activeSet
)) ) {
1999 show_active(" ", act
);
2002 VG_(message
)(Vg_DebugMsg
, ">>\n");
2005 /*--------------------------------------------------------------------*/
2007 /*--------------------------------------------------------------------*/