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