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-2013 Julian Seward
11 jseward@acm.org
12 Copyright (C) 2003-2013 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(const HChar* ec, SizeT);
306 static void dinfo_free(void*);
307 static HChar* dinfo_strdup(const HChar* ec, const HChar*);
308 static Bool is_plausible_guest_addr(Addr);
309
310 static void show_redir_state ( const HChar* who );
311 static void show_active ( const HChar* left, Active* act );
312
313 static void handle_maybe_load_notifier( const HChar* 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(HChar * pri_name,HChar ** sec_names,HChar ** twoslots)337 static HChar** alloc_symname_array ( HChar* pri_name, HChar** sec_names,
338 HChar** 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 HChar** pp = sec_names;
350 while (*pp) { n_req++; pp++; }
351 /* .. allocate and copy in. */
352 HChar** arr = dinfo_zalloc( "redir.asa.1", (n_req+1) * sizeof(HChar*) );
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(HChar ** names,HChar ** twoslots)364 static void free_symname_array ( HChar** names, HChar** 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 HChar* sym_name_pri;
399 HChar** 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 HChar* 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 HChar* newdi_filename = VG_(DebugInfo_get_filename)(newdi);
441 const HChar* 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 HChar 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 HChar* twoslots[2];
507 HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec,
508 &twoslots[0]);
509 HChar** 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 HChar* twoslots[2];
599 HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec,
600 &twoslots[0]);
601 HChar** 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 HChar* sym_name_pri;
737 HChar** 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 HChar* twoslots[2];
762 HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec,
763 &twoslots[0]);
764 HChar** 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 const 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 const 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(const HChar * sopatt,const HChar * fnpatt,Addr to_addr,const HChar ** mandatory)1132 static void add_hardwired_spec (const HChar* sopatt, const 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 = (HChar *)sopatt;
1150 spec->from_fnpatt = (HChar *)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 the
1303 start, otherwise ld.so makes a lot of noise. In most ARM-linux
1304 distros, ld.so's soname is ld-linux.so.3, but Ubuntu 14.04 on
1305 Odroid uses ld-linux-armhf.so.3 for some reason. */
1306 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
1307 /* strlen */
1308 add_hardwired_spec(
1309 "ld-linux.so.3", "strlen",
1310 (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
1311 complain_about_stripped_glibc_ldso
1312 );
1313 add_hardwired_spec(
1314 "ld-linux-armhf.so.3", "strlen",
1315 (Addr)&VG_(arm_linux_REDIR_FOR_strlen),
1316 complain_about_stripped_glibc_ldso
1317 );
1318 /* memcpy */
1319 add_hardwired_spec(
1320 "ld-linux.so.3", "memcpy",
1321 (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
1322 complain_about_stripped_glibc_ldso
1323 );
1324 add_hardwired_spec(
1325 "ld-linux-armhf.so.3", "memcpy",
1326 (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
1327 complain_about_stripped_glibc_ldso
1328 );
1329 }
1330
1331 # elif defined(VGP_arm64_linux)
1332 /* If we're using memcheck, use these intercepts right from
1333 the start, otherwise ld.so makes a lot of noise. */
1334 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
1335 add_hardwired_spec(
1336 "ld-linux-aarch64.so.1", "strlen",
1337 (Addr)&VG_(arm64_linux_REDIR_FOR_strlen),
1338 complain_about_stripped_glibc_ldso
1339 );
1340 add_hardwired_spec(
1341 "ld-linux-aarch64.so.1", "index",
1342 (Addr)&VG_(arm64_linux_REDIR_FOR_index),
1343 NULL
1344 );
1345 add_hardwired_spec(
1346 "ld-linux-aarch64.so.1", "strcmp",
1347 (Addr)&VG_(arm64_linux_REDIR_FOR_strcmp),
1348 NULL
1349 );
1350 //add_hardwired_spec(
1351 // "ld-linux.so.3", "memcpy",
1352 // (Addr)&VG_(arm_linux_REDIR_FOR_memcpy),
1353 // complain_about_stripped_glibc_ldso
1354 //);
1355 }
1356
1357 # elif defined(VGP_x86_darwin)
1358 /* If we're using memcheck, use these intercepts right from
1359 the start, otherwise dyld makes a lot of noise. */
1360 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
1361 add_hardwired_spec("dyld", "strcmp",
1362 (Addr)&VG_(x86_darwin_REDIR_FOR_strcmp), NULL);
1363 add_hardwired_spec("dyld", "strlen",
1364 (Addr)&VG_(x86_darwin_REDIR_FOR_strlen), NULL);
1365 add_hardwired_spec("dyld", "strcat",
1366 (Addr)&VG_(x86_darwin_REDIR_FOR_strcat), NULL);
1367 add_hardwired_spec("dyld", "strcpy",
1368 (Addr)&VG_(x86_darwin_REDIR_FOR_strcpy), NULL);
1369 add_hardwired_spec("dyld", "strlcat",
1370 (Addr)&VG_(x86_darwin_REDIR_FOR_strlcat), NULL);
1371 }
1372
1373 # elif defined(VGP_amd64_darwin)
1374 /* If we're using memcheck, use these intercepts right from
1375 the start, otherwise dyld makes a lot of noise. */
1376 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
1377 add_hardwired_spec("dyld", "strcmp",
1378 (Addr)&VG_(amd64_darwin_REDIR_FOR_strcmp), NULL);
1379 add_hardwired_spec("dyld", "strlen",
1380 (Addr)&VG_(amd64_darwin_REDIR_FOR_strlen), NULL);
1381 add_hardwired_spec("dyld", "strcat",
1382 (Addr)&VG_(amd64_darwin_REDIR_FOR_strcat), NULL);
1383 add_hardwired_spec("dyld", "strcpy",
1384 (Addr)&VG_(amd64_darwin_REDIR_FOR_strcpy), NULL);
1385 add_hardwired_spec("dyld", "strlcat",
1386 (Addr)&VG_(amd64_darwin_REDIR_FOR_strlcat), NULL);
1387 // DDD: #warning fixme rdar://6166275
1388 add_hardwired_spec("dyld", "arc4random",
1389 (Addr)&VG_(amd64_darwin_REDIR_FOR_arc4random), NULL);
1390 }
1391
1392 # elif defined(VGP_s390x_linux)
1393 /* nothing so far */
1394
1395 # elif defined(VGP_mips32_linux)
1396 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
1397
1398 /* this is mandatory - can't sanely continue without it */
1399 add_hardwired_spec(
1400 "ld.so.3", "strlen",
1401 (Addr)&VG_(mips32_linux_REDIR_FOR_strlen),
1402 complain_about_stripped_glibc_ldso
1403 );
1404 }
1405
1406 # elif defined(VGP_mips64_linux)
1407 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
1408
1409 /* this is mandatory - can't sanely continue without it */
1410 add_hardwired_spec(
1411 "ld.so.3", "strlen",
1412 (Addr)&VG_(mips64_linux_REDIR_FOR_strlen),
1413 complain_about_stripped_glibc_ldso
1414 );
1415 }
1416
1417 # else
1418 # error Unknown platform
1419 # endif
1420
1421 if (VG_(clo_trace_redir))
1422 show_redir_state("after VG_(redir_initialise)");
1423 }
1424
1425
1426 /*------------------------------------------------------------*/
1427 /*--- MISC HELPERS ---*/
1428 /*------------------------------------------------------------*/
1429
dinfo_zalloc(const HChar * ec,SizeT n)1430 static void* dinfo_zalloc(const HChar* ec, SizeT n) {
1431 void* p;
1432 vg_assert(n > 0);
1433 p = VG_(arena_malloc)(VG_AR_DINFO, ec, n);
1434 tl_assert(p);
1435 VG_(memset)(p, 0, n);
1436 return p;
1437 }
1438
dinfo_free(void * p)1439 static void dinfo_free(void* p) {
1440 tl_assert(p);
1441 return VG_(arena_free)(VG_AR_DINFO, p);
1442 }
1443
dinfo_strdup(const HChar * ec,const HChar * str)1444 static HChar* dinfo_strdup(const HChar* ec, const HChar* str)
1445 {
1446 return VG_(arena_strdup)(VG_AR_DINFO, ec, str);
1447 }
1448
1449 /* Really this should be merged with translations_allowable_from_seg
1450 in m_translate. */
is_plausible_guest_addr(Addr a)1451 static Bool is_plausible_guest_addr(Addr a)
1452 {
1453 NSegment const* seg = VG_(am_find_nsegment)(a);
1454 return seg != NULL
1455 && (seg->kind == SkAnonC || seg->kind == SkFileC)
1456 && (seg->hasX || seg->hasR); /* crude x86-specific hack */
1457 }
1458
1459
1460 /*------------------------------------------------------------*/
1461 /*--- NOTIFY-ON-LOAD FUNCTIONS ---*/
1462 /*------------------------------------------------------------*/
1463
1464 static
handle_maybe_load_notifier(const HChar * soname,HChar * symbol,Addr addr)1465 void handle_maybe_load_notifier( const HChar* soname,
1466 HChar* symbol, Addr addr )
1467 {
1468 # if defined(VGP_x86_linux)
1469 /* x86-linux only: if we see _dl_sysinfo_int80, note its address.
1470 See comment on declaration of VG_(client__dl_sysinfo_int80) for
1471 the reason. As far as I can tell, the relevant symbol is always
1472 in object with soname "ld-linux.so.2". */
1473 if (symbol && symbol[0] == '_'
1474 && 0 == VG_(strcmp)(symbol, "_dl_sysinfo_int80")
1475 && 0 == VG_(strcmp)(soname, "ld-linux.so.2")) {
1476 if (VG_(client__dl_sysinfo_int80) == 0)
1477 VG_(client__dl_sysinfo_int80) = addr;
1478 }
1479 # endif
1480
1481 /* Normal load-notifier handling after here. First, ignore all
1482 symbols lacking the right prefix. */
1483 vg_assert(symbol); // assert rather than segfault if it is NULL
1484 if (0 != VG_(strncmp)(symbol, VG_NOTIFY_ON_LOAD_PREFIX,
1485 VG_NOTIFY_ON_LOAD_PREFIX_LEN))
1486 /* Doesn't have the right prefix */
1487 return;
1488
1489 if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0)
1490 VG_(client___libc_freeres_wrapper) = addr;
1491 else
1492 if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0)
1493 iFuncWrapper = addr;
1494 else
1495 vg_assert2(0, "unrecognised load notification function: %s", symbol);
1496 }
1497
1498
1499 /*------------------------------------------------------------*/
1500 /*--- REQUIRE-TEXT-SYMBOL HANDLING ---*/
1501 /*------------------------------------------------------------*/
1502
1503 /* In short: check that the currently-being-loaded object has text
1504 symbols that satisfy any --require-text-symbol= specifications that
1505 apply to it, and abort the run with an error message if not.
1506 */
handle_require_text_symbols(DebugInfo * di)1507 static void handle_require_text_symbols ( DebugInfo* di )
1508 {
1509 /* First thing to do is figure out which, if any,
1510 --require-text-symbol specification strings apply to this
1511 object. Most likely none do, since it is not expected to
1512 frequently be used. Work through the list of specs and
1513 accumulate in fnpatts[] the fn patterns that pertain to this
1514 object. */
1515 HChar* fnpatts[VG_CLO_MAX_REQ_TSYMS];
1516 Int fnpatts_used = 0;
1517 Int i, j;
1518 const HChar* di_soname = VG_(DebugInfo_get_soname)(di);
1519 vg_assert(di_soname); // must be present
1520
1521 VG_(memset)(&fnpatts, 0, sizeof(fnpatts));
1522
1523 vg_assert(VG_(clo_n_req_tsyms) >= 0);
1524 vg_assert(VG_(clo_n_req_tsyms) <= VG_CLO_MAX_REQ_TSYMS);
1525 for (i = 0; i < VG_(clo_n_req_tsyms); i++) {
1526 const HChar* clo_spec = VG_(clo_req_tsyms)[i];
1527 vg_assert(clo_spec && VG_(strlen)(clo_spec) >= 4);
1528 // clone the spec, so we can stick a zero at the end of the sopatt
1529 HChar *spec = VG_(strdup)("m_redir.hrts.1", clo_spec);
1530 HChar sep = spec[0];
1531 HChar* sopatt = &spec[1];
1532 HChar* fnpatt = VG_(strchr)(sopatt, sep);
1533 // the initial check at clo processing in time in m_main
1534 // should ensure this.
1535 vg_assert(fnpatt && *fnpatt == sep);
1536 *fnpatt = 0;
1537 fnpatt++;
1538 if (VG_(string_match)(sopatt, di_soname))
1539 fnpatts[fnpatts_used++]
1540 = VG_(strdup)("m_redir.hrts.2", fnpatt);
1541 VG_(free)(spec);
1542 }
1543
1544 if (fnpatts_used == 0)
1545 return; /* no applicable spec strings */
1546
1547 /* So finally, fnpatts[0 .. fnpatts_used - 1] contains the set of
1548 (patterns for) text symbol names that must be found in this
1549 object, in order to continue. That is, we must find at least
1550 one text symbol name that matches each pattern, else we must
1551 abort the run. */
1552
1553 if (0) VG_(printf)("for %s\n", di_soname);
1554 for (i = 0; i < fnpatts_used; i++)
1555 if (0) VG_(printf)(" fnpatt: %s\n", fnpatts[i]);
1556
1557 /* For each spec, look through the syms to find one that matches.
1558 This isn't terribly efficient but it happens rarely, so no big
1559 deal. */
1560 for (i = 0; i < fnpatts_used; i++) {
1561 Bool found = False;
1562 HChar* fnpatt = fnpatts[i];
1563 Int nsyms = VG_(DebugInfo_syms_howmany)(di);
1564 for (j = 0; j < nsyms; j++) {
1565 Bool isText = False;
1566 HChar* sym_name_pri = NULL;
1567 HChar** sym_names_sec = NULL;
1568 VG_(DebugInfo_syms_getidx)( di, j, NULL, NULL,
1569 NULL, &sym_name_pri, &sym_names_sec,
1570 &isText, NULL );
1571 HChar* twoslots[2];
1572 HChar** names_init = alloc_symname_array(sym_name_pri, sym_names_sec,
1573 &twoslots[0]);
1574 HChar** names;
1575 for (names = names_init; *names; names++) {
1576 /* ignore data symbols */
1577 if (0) VG_(printf)("QQQ %s\n", *names);
1578 vg_assert(sym_name_pri);
1579 if (!isText)
1580 continue;
1581 if (VG_(string_match)(fnpatt, *names)) {
1582 found = True;
1583 break;
1584 }
1585 }
1586 free_symname_array(names_init, &twoslots[0]);
1587 if (found)
1588 break;
1589 }
1590
1591 if (!found) {
1592 const HChar* v = "valgrind: ";
1593 VG_(printf)("\n");
1594 VG_(printf)(
1595 "%sFatal error at when loading library with soname\n", v);
1596 VG_(printf)(
1597 "%s %s\n", v, di_soname);
1598 VG_(printf)(
1599 "%sCannot find any text symbol with a name "
1600 "that matches the pattern\n", v);
1601 VG_(printf)("%s %s\n", v, fnpatt);
1602 VG_(printf)("%sas required by a --require-text-symbol= "
1603 "specification.\n", v);
1604 VG_(printf)("\n");
1605 VG_(printf)(
1606 "%sCannot continue -- exiting now.\n", v);
1607 VG_(printf)("\n");
1608 VG_(exit)(1);
1609 }
1610 }
1611
1612 /* All required specs were found. Just free memory and return. */
1613 for (i = 0; i < fnpatts_used; i++)
1614 VG_(free)(fnpatts[i]);
1615 }
1616
1617
1618 /*------------------------------------------------------------*/
1619 /*--- SANITY/DEBUG ---*/
1620 /*------------------------------------------------------------*/
1621
show_spec(const HChar * left,Spec * spec)1622 static void show_spec ( const HChar* left, Spec* spec )
1623 {
1624 VG_(message)( Vg_DebugMsg,
1625 "%s%25s %30s %s-> (%04d.%d) 0x%08llx\n",
1626 left,
1627 spec->from_sopatt, spec->from_fnpatt,
1628 spec->isWrap ? "W" : "R",
1629 spec->becTag, spec->becPrio,
1630 (ULong)spec->to_addr );
1631 }
1632
show_active(const HChar * left,Active * act)1633 static void show_active ( const HChar* left, Active* act )
1634 {
1635 Bool ok;
1636 HChar name1[64] = "";
1637 HChar name2[64] = "";
1638 name1[0] = name2[0] = 0;
1639 ok = VG_(get_fnname_w_offset)(act->from_addr, name1, 64);
1640 if (!ok) VG_(strcpy)(name1, "???");
1641 ok = VG_(get_fnname_w_offset)(act->to_addr, name2, 64);
1642 if (!ok) VG_(strcpy)(name2, "???");
1643
1644 VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> (%04d.%d) 0x%08llx %s\n",
1645 left,
1646 (ULong)act->from_addr, name1,
1647 act->isWrap ? "W" : "R",
1648 act->becTag, act->becPrio,
1649 (ULong)act->to_addr, name2 );
1650 }
1651
show_redir_state(const HChar * who)1652 static void show_redir_state ( const HChar* who )
1653 {
1654 TopSpec* ts;
1655 Spec* sp;
1656 Active* act;
1657 VG_(message)(Vg_DebugMsg, "<<\n");
1658 VG_(message)(Vg_DebugMsg, " ------ REDIR STATE %s ------\n", who);
1659 for (ts = topSpecs; ts; ts = ts->next) {
1660 if (ts->seginfo)
1661 VG_(message)(Vg_DebugMsg,
1662 " TOPSPECS of soname %s filename %s\n",
1663 VG_(DebugInfo_get_soname)(ts->seginfo),
1664 VG_(DebugInfo_get_filename)(ts->seginfo));
1665 else
1666 VG_(message)(Vg_DebugMsg,
1667 " TOPSPECS of soname (hardwired)\n");
1668
1669 for (sp = ts->specs; sp; sp = sp->next)
1670 show_spec(" ", sp);
1671 }
1672 VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------\n");
1673 VG_(OSetGen_ResetIter)( activeSet );
1674 while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
1675 show_active(" ", act);
1676 }
1677
1678 VG_(message)(Vg_DebugMsg, ">>\n");
1679 }
1680
1681 /*--------------------------------------------------------------------*/
1682 /*--- end ---*/
1683 /*--------------------------------------------------------------------*/
1684