blob: f4787079cf9fc1437a2d5bc2dfa008c25c55f13f [file] [log] [blame]
njnc0ae7052005-08-25 22:55:19 +00001
sewardjcbdddcf2005-03-10 23:23:45 +00002/*--------------------------------------------------------------------*/
njnc0ae7052005-08-25 22:55:19 +00003/*--- Function replacement and wrapping. m_redir.c ---*/
sewardjcbdddcf2005-03-10 23:23:45 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc0ae7052005-08-25 22:55:19 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjcbdddcf2005-03-10 23:23:45 +00009
sewardj4d474d02008-02-11 11:34:59 +000010 Copyright (C) 2000-2008 Julian Seward
sewardjcbdddcf2005-03-10 23:23:45 +000011 jseward@acm.org
sewardj4d474d02008-02-11 11:34:59 +000012 Copyright (C) 2003-2008 Jeremy Fitzhardinge
sewardjcbdddcf2005-03-10 23:23:45 +000013 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*/
sewardjcbdddcf2005-03-10 23:23:45 +000032
njnc7561b92005-06-19 01:24:32 +000033#include "pub_core_basics.h"
sewardj45f4e7c2005-09-27 19:20:21 +000034#include "pub_core_debuglog.h"
njn88c51482005-06-25 20:49:33 +000035#include "pub_core_debuginfo.h"
njn97405b22005-06-02 03:39:33 +000036#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000038#include "pub_core_libcprint.h"
njnaf1d7df2005-06-11 01:31:52 +000039#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000040#include "pub_core_options.h"
njn8a96ec52005-10-15 15:48:52 +000041#include "pub_core_oset.h"
njnd1af0032005-05-29 17:01:48 +000042#include "pub_core_redir.h"
njna7598f62005-06-18 03:27:58 +000043#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000044#include "pub_core_transtab.h"
sewardj461c69d2005-11-17 20:15:04 +000045#include "pub_core_tooliface.h" // VG_(needs).malloc_replacement
sewardj6b9cc872006-10-17 01:39:30 +000046#include "pub_core_machine.h" // VG_(fnptr_to_fnentry)
sewardj0ec07f32006-01-12 12:32:32 +000047#include "pub_core_aspacemgr.h" // VG_(am_find_nsegment)
sewardj14c7cc52007-02-25 15:08:24 +000048#include "pub_core_xarray.h"
sewardj0ec07f32006-01-12 12:32:32 +000049#include "pub_core_clientstate.h" // VG_(client___libc_freeres_wrapper)
50#include "pub_core_demangle.h" // VG_(maybe_Z_demangle)
sewardj461c69d2005-11-17 20:15:04 +000051
sewardj55f9d1a2005-04-25 11:11:44 +000052
sewardj0ec07f32006-01-12 12:32:32 +000053/* This module is a critical part of the redirection/intercept system.
54 It keeps track of the current intercept state, cleans up the
55 translation caches when that state changes, and finally, answers
56 queries about the whether an address is currently redirected or
57 not. It doesn't do any of the control-flow trickery needed to put
58 the redirections into practice. That is the job of m_translate,
59 which calls here to find out which translations need to be
60 redirected.
61
62 The interface is simple. VG_(redir_initialise) initialises and
63 loads some hardwired redirects which never disappear; this is
64 platform-specific.
65
66 The module is notified of redirection state changes by m_debuginfo.
67 That calls VG_(redir_notify_new_SegInfo) when a new SegInfo (shared
68 object symbol table, basically) appears. Appearance of new symbols
69 can cause new (active) redirections to appear for two reasons: the
70 symbols in the new table may match existing redirection
71 specifications (see comments below), and because the symbols in the
72 new table may themselves supply new redirect specifications which
73 match existing symbols (or ones in the new table).
74
75 Redirect specifications are really symbols with "funny" prefixes
76 (_vgrZU_ and _vgrZZ_). These names tell m_redir that the
77 associated code should replace the standard entry point for some
78 set of functions. The set of functions is specified by a (soname
79 pattern, function name pattern) pair which is encoded in the symbol
80 name following the prefix. The names use a Z-encoding scheme so
81 that they may contain punctuation characters and wildcards (*).
82 The encoding scheme is described in pub_tool_redir.h and is decoded
83 by VG_(maybe_Z_demangle).
84
85 When a shared object is unloaded, this module learns of it via a
86 call to VG_(redir_notify_delete_SegInfo). It then removes from its
87 tables all active redirections in any way associated with that
88 object, and tidies up the translation caches accordingly.
89
90 That takes care of tracking the redirection state. When a
91 translation is actually to be made, m_translate calls to
92 VG_(redir_do_lookup) in this module to find out if the
93 translation's address should be redirected.
94*/
95
sewardjcbdddcf2005-03-10 23:23:45 +000096/*------------------------------------------------------------*/
sewardj0ec07f32006-01-12 12:32:32 +000097/*--- Semantics ---*/
sewardjcbdddcf2005-03-10 23:23:45 +000098/*------------------------------------------------------------*/
99
sewardj0ec07f32006-01-12 12:32:32 +0000100/* The redirector holds two pieces of state:
njnd9109c62005-06-26 04:49:25 +0000101
sewardj0ec07f32006-01-12 12:32:32 +0000102 Specs - a set of (soname pattern, fnname pattern) -> redir addr
103 Active - a set of orig addr -> (bool, redir addr)
sewardjcbdddcf2005-03-10 23:23:45 +0000104
sewardj0ec07f32006-01-12 12:32:32 +0000105 Active is the currently active set of bindings that the translator
106 consults. Specs is the current set of specifications as harvested
107 from reading symbol tables of the currently loaded objects.
sewardjcbdddcf2005-03-10 23:23:45 +0000108
sewardj0ec07f32006-01-12 12:32:32 +0000109 Active is a pure function of Specs and the current symbol table
110 state (maintained by m_debuginfo). Call the latter SyminfoState.
sewardjcbdddcf2005-03-10 23:23:45 +0000111
sewardj0ec07f32006-01-12 12:32:32 +0000112 Therefore whenever either Specs or SyminfoState changes, Active
113 must be recomputed. [Inefficient if done naively, but this is a
114 spec].
njn8a96ec52005-10-15 15:48:52 +0000115
sewardj0ec07f32006-01-12 12:32:32 +0000116 Active is computed as follows:
sewardjcbdddcf2005-03-10 23:23:45 +0000117
sewardj0ec07f32006-01-12 12:32:32 +0000118 Active = empty
119 for spec in Specs {
120 sopatt = spec.soname pattern
121 fnpatt = spec.fnname pattern
122 redir = spec.redir addr
123 for so matching sopatt in SyminfoState {
124 for fn matching fnpatt in fnnames_of(so) {
125 &fn -> redir is added to Active
126 }
127 }
tom748a1312005-04-02 15:53:01 +0000128 }
129
sewardj0ec07f32006-01-12 12:32:32 +0000130 [as an implementation detail, when a binding (orig -> redir) is
131 deleted from Active as a result of recomputing it, then all
132 translations intersecting redir must be deleted. However, this is
133 not part of the spec].
134
135 [Active also depends on where the aspacemgr has decided to put all
136 the pieces of code -- that affects the "orig addr" and "redir addr"
137 values.]
138
139 ---------------------
140
141 That completes the spec, apart from one difficult issue: duplicates.
142
143 Clearly we must impose the requirement that domain(Active) contains
144 no duplicates. The difficulty is how to constrain Specs enough to
145 avoid getting into that situation. It's easy to write specs which
146 could cause conflicting bindings in Active, eg:
147
148 (libpthread.so, pthread_mutex_lock) -> a1
149 (libpthread.so, pthread_*) -> a2
150
151 for a1 != a2. Or even hairier:
152
153 (libpthread.so, pthread_mutex_*) -> a1
154 (libpthread.so, pthread_*_lock) -> a2
155
156 I can't think of any sane way of detecting when an addition to
157 Specs would generate conflicts. However, considering we don't
158 actually want to have a system that allows this, I propose this:
159 all changes to Specs are acceptable. But, when recomputing Active
160 following the change, if the same orig is bound to more than one
161 redir, then the first binding for orig is retained, and all the
162 rest ignored.
163
164 ===========================================================
165 ===========================================================
166 Incremental implementation:
167
168 When a new SegInfo appears:
169 - it may be the source of new specs
170 - it may be the source of new matches for existing specs
171 Therefore:
172
173 - (new Specs x existing SegInfos): scan all symbols in the new
174 SegInfo to find new specs. Each of these needs to be compared
175 against all symbols in all the existing SegInfos to generate
176 new actives.
177
178 - (existing Specs x new SegInfo): scan all symbols in the SegInfo,
179 trying to match them to any existing specs, also generating
180 new actives.
181
182 - (new Specs x new SegInfo): scan all symbols in the new SegInfo,
183 trying to match them against the new specs, to generate new
184 actives.
185
186 - Finally, add new new specs to the current set of specs.
187
188 When adding a new active (s,d) to the Actives:
189 lookup s in Actives
190 if already bound to d, ignore
191 if already bound to something other than d, complain loudly and ignore
192 else add (s,d) to Actives
193 and discard (s,1) and (d,1) (maybe overly conservative)
194
195 When a SegInfo disappears:
196 - delete all specs acquired from the seginfo
197 - delete all actives derived from the just-deleted specs
198 - if each active (s,d) deleted, discard (s,1) and (d,1)
199*/
200
201
202/*------------------------------------------------------------*/
203/*--- REDIRECTION SPECIFICATIONS ---*/
204/*------------------------------------------------------------*/
205
206/* A specification of a redirection we want to do. Note that because
207 both the "from" soname and function name may contain wildcards, the
sewardj5092a972007-11-16 18:45:40 +0000208 spec can match an arbitrary number of times.
209
210 16 Nov 2007: Comments re .mandatory field: The initial motivation
211 for this is making Memcheck work sanely on glibc-2.6.X ppc32-linux.
212 We really need to intercept 'strlen' in ld.so right from startup.
213 If ld.so does not have a visible 'strlen' symbol, Memcheck
214 generates an impossible number of errors resulting from highly
215 tuned strlen implementation in ld.so, and is completely unusable
216 -- the resulting undefinedness eventually seeps everywhere. */
sewardj0ec07f32006-01-12 12:32:32 +0000217typedef
218 struct _Spec {
219 struct _Spec* next; /* linked list */
sewardjdf24cf12007-11-16 18:32:40 +0000220 /* FIXED PARTS -- set when created and not changed */
sewardj0ec07f32006-01-12 12:32:32 +0000221 HChar* from_sopatt; /* from soname pattern */
222 HChar* from_fnpatt; /* from fnname pattern */
223 Addr to_addr; /* where redirecting to */
224 Bool isWrap; /* wrap or replacement? */
sewardjdf24cf12007-11-16 18:32:40 +0000225 HChar* mandatory; /* non-NULL ==> abort V and print the
226 string if from_sopatt is loaded but
227 from_fnpatt cannot be found */
228 /* VARIABLE PARTS -- used transiently whilst processing redirections */
229 Bool mark; /* set if spec requires further processing */
230 Bool done; /* set if spec was successfully matched */
sewardj0ec07f32006-01-12 12:32:32 +0000231 }
232 Spec;
233
234/* Top-level data structure. It contains a pointer to a SegInfo and
235 also a list of the specs harvested from that SegInfo. Note that
236 seginfo is allowed to be NULL, meaning that the specs are
237 pre-loaded ones at startup and are not associated with any
238 particular seginfo. */
239typedef
240 struct _TopSpec {
241 struct _TopSpec* next; /* linked list */
sewardjb8b79ad2008-03-03 01:35:41 +0000242 DebugInfo* seginfo; /* symbols etc */
243 Spec* specs; /* specs pulled out of seginfo */
244 Bool mark; /* transient temporary used during deletion */
sewardj0ec07f32006-01-12 12:32:32 +0000245 }
246 TopSpec;
247
248/* This is the top level list of redirections. m_debuginfo maintains
249 a list of SegInfos, and the idea here is to maintain a list with
250 the same number of elements (in fact, with one more element, so as
251 to record abovementioned preloaded specifications.) */
252static TopSpec* topSpecs = NULL;
253
254
255/*------------------------------------------------------------*/
256/*--- CURRENTLY ACTIVE REDIRECTIONS ---*/
257/*------------------------------------------------------------*/
258
259/* Represents a currently active binding. If either parent_spec or
260 parent_sym is NULL, then this binding was hardwired at startup and
261 should not be deleted. Same is true if either parent's seginfo
262 field is NULL. */
263typedef
264 struct {
265 Addr from_addr; /* old addr -- MUST BE THE FIRST WORD! */
266 Addr to_addr; /* where redirecting to */
267 TopSpec* parent_spec; /* the TopSpec which supplied the Spec */
268 TopSpec* parent_sym; /* the TopSpec which supplied the symbol */
269 Bool isWrap; /* wrap or replacement? */
270 }
271 Active;
272
273/* The active set is a fast lookup table */
274static OSet* activeSet = NULL;
275
276
277/*------------------------------------------------------------*/
278/*--- FWDses ---*/
279/*------------------------------------------------------------*/
280
281static void maybe_add_active ( Active /*by value; callee copies*/ );
282
sewardjb8b79ad2008-03-03 01:35:41 +0000283static void* dinfo_zalloc(SizeT);
284static void dinfo_free(void*);
285static HChar* dinfo_strdup(HChar*);
sewardj0ec07f32006-01-12 12:32:32 +0000286static Bool is_plausible_guest_addr(Addr);
sewardj6b9cc872006-10-17 01:39:30 +0000287static Bool is_aix5_glink_idiom(Addr);
sewardj0ec07f32006-01-12 12:32:32 +0000288
289static void show_redir_state ( HChar* who );
290static void show_active ( HChar* left, Active* act );
291
sewardja672ea32006-04-29 18:03:14 +0000292static void handle_maybe_load_notifier( const UChar* soname,
293 HChar* symbol, Addr addr );
sewardj0ec07f32006-01-12 12:32:32 +0000294
295
296/*------------------------------------------------------------*/
297/*--- NOTIFICATIONS ---*/
298/*------------------------------------------------------------*/
299
300static
301void generate_and_add_actives (
302 /* spec list and the owning TopSpec */
303 Spec* specs,
304 TopSpec* parent_spec,
sewardjb8b79ad2008-03-03 01:35:41 +0000305 /* debuginfo and the owning TopSpec */
306 DebugInfo* di,
sewardj0ec07f32006-01-12 12:32:32 +0000307 TopSpec* parent_sym
308 );
309
sewardjb8b79ad2008-03-03 01:35:41 +0000310/* Notify m_redir of the arrival of a new DebugInfo. This is fairly
sewardj0ec07f32006-01-12 12:32:32 +0000311 complex, but the net effect is to (1) add a new entry to the
312 topspecs list, and (2) figure out what new binding are now active,
313 and, as a result, add them to the actives mapping. */
314
315#define N_DEMANGLED 256
316
sewardjb8b79ad2008-03-03 01:35:41 +0000317void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
sewardj0ec07f32006-01-12 12:32:32 +0000318{
sewardj6b9cc872006-10-17 01:39:30 +0000319 Bool ok, isWrap;
320 Int i, nsyms;
321 Spec* specList;
322 Spec* spec;
323 TopSpec* ts;
324 TopSpec* newts;
325 HChar* sym_name;
326 Addr sym_addr, sym_toc;
327 HChar demangled_sopatt[N_DEMANGLED];
328 HChar demangled_fnpatt[N_DEMANGLED];
329 Bool check_ppcTOCs = False;
sewardjb8b79ad2008-03-03 01:35:41 +0000330 Bool isText;
sewardja672ea32006-04-29 18:03:14 +0000331 const UChar* newsi_soname;
332
sewardj6b9cc872006-10-17 01:39:30 +0000333# if defined(VG_PLAT_USES_PPCTOC)
334 check_ppcTOCs = True;
335# endif
336
sewardj0ec07f32006-01-12 12:32:32 +0000337 vg_assert(newsi);
sewardja672ea32006-04-29 18:03:14 +0000338 newsi_soname = VG_(seginfo_soname)(newsi);
339 vg_assert(newsi_soname != NULL);
sewardj0ec07f32006-01-12 12:32:32 +0000340
341 /* stay sane: we don't already have this. */
342 for (ts = topSpecs; ts; ts = ts->next)
343 vg_assert(ts->seginfo != newsi);
344
sewardjb8b79ad2008-03-03 01:35:41 +0000345 /* scan this DebugInfo's symbol table, pulling out and demangling
sewardj0ec07f32006-01-12 12:32:32 +0000346 any specs found */
347
348 specList = NULL; /* the spec list we're building up */
349
350 nsyms = VG_(seginfo_syms_howmany)( newsi );
351 for (i = 0; i < nsyms; i++) {
sewardj6b9cc872006-10-17 01:39:30 +0000352 VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
sewardjb8b79ad2008-03-03 01:35:41 +0000353 NULL, &sym_name, &isText );
sewardj0ec07f32006-01-12 12:32:32 +0000354 ok = VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANGLED,
sewardj6b9cc872006-10-17 01:39:30 +0000355 demangled_fnpatt, N_DEMANGLED, &isWrap );
sewardjb8b79ad2008-03-03 01:35:41 +0000356 /* ignore data symbols */
357 if (!isText)
358 continue;
sewardj0ec07f32006-01-12 12:32:32 +0000359 if (!ok) {
360 /* It's not a full-scale redirect, but perhaps it is a load-notify
361 fn? Let the load-notify department see it. */
sewardja672ea32006-04-29 18:03:14 +0000362 handle_maybe_load_notifier( newsi_soname, sym_name, sym_addr );
sewardj0ec07f32006-01-12 12:32:32 +0000363 continue;
364 }
sewardj6b9cc872006-10-17 01:39:30 +0000365 if (check_ppcTOCs && sym_toc == 0) {
366 /* This platform uses toc pointers, but none could be found
367 for this symbol, so we can't safely redirect/wrap to it.
368 Just skip it; we'll make a second pass over the symbols in
369 the following loop, and complain at that point. */
370 continue;
371 }
sewardjb8b79ad2008-03-03 01:35:41 +0000372 spec = dinfo_zalloc(sizeof(Spec));
sewardj0ec07f32006-01-12 12:32:32 +0000373 vg_assert(spec);
sewardjb8b79ad2008-03-03 01:35:41 +0000374 spec->from_sopatt = dinfo_strdup(demangled_sopatt);
375 spec->from_fnpatt = dinfo_strdup(demangled_fnpatt);
sewardj0ec07f32006-01-12 12:32:32 +0000376 vg_assert(spec->from_sopatt);
377 vg_assert(spec->from_fnpatt);
378 spec->to_addr = sym_addr;
379 spec->isWrap = isWrap;
380 /* check we're not adding manifestly stupid destinations */
381 vg_assert(is_plausible_guest_addr(sym_addr));
382 spec->next = specList;
383 spec->mark = False; /* not significant */
sewardjdf24cf12007-11-16 18:32:40 +0000384 spec->done = False; /* not significant */
sewardj0ec07f32006-01-12 12:32:32 +0000385 specList = spec;
386 }
387
sewardj6b9cc872006-10-17 01:39:30 +0000388 if (check_ppcTOCs) {
389 for (i = 0; i < nsyms; i++) {
390 VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
sewardjb8b79ad2008-03-03 01:35:41 +0000391 NULL, &sym_name, &isText );
392 ok = isText
393 && VG_(maybe_Z_demangle)(
394 sym_name, demangled_sopatt, N_DEMANGLED,
395 demangled_fnpatt, N_DEMANGLED, &isWrap );
sewardj6b9cc872006-10-17 01:39:30 +0000396 if (!ok)
397 /* not a redirect. Ignore. */
398 continue;
399 if (sym_toc != 0)
400 /* has a valid toc pointer. Ignore. */
401 continue;
402
403 for (spec = specList; spec; spec = spec->next)
404 if (0 == VG_(strcmp)(spec->from_sopatt, demangled_sopatt)
405 && 0 == VG_(strcmp)(spec->from_fnpatt, demangled_fnpatt))
406 break;
407 if (spec)
sewardjdf24cf12007-11-16 18:32:40 +0000408 /* a redirect to some other copy of that symbol, which
409 does have a TOC value, already exists */
410 continue;
sewardj6b9cc872006-10-17 01:39:30 +0000411
412 /* Complain */
413 VG_(message)(Vg_DebugMsg,
414 "WARNING: no TOC ptr for redir/wrap to %s %s",
415 demangled_sopatt, demangled_fnpatt);
416 }
417 }
418
sewardjb8b79ad2008-03-03 01:35:41 +0000419 /* Ok. Now specList holds the list of specs from the DebugInfo.
sewardj0ec07f32006-01-12 12:32:32 +0000420 Build a new TopSpec, but don't add it to topSpecs yet. */
sewardjb8b79ad2008-03-03 01:35:41 +0000421 newts = dinfo_zalloc(sizeof(TopSpec));
sewardj0ec07f32006-01-12 12:32:32 +0000422 vg_assert(newts);
423 newts->next = NULL; /* not significant */
424 newts->seginfo = newsi;
425 newts->specs = specList;
426 newts->mark = False; /* not significant */
427
428 /* We now need to augment the active set with the following partial
429 cross product:
430
431 (1) actives formed by matching the new specs in specList against
432 all symbols currently listed in topSpecs
433
434 (2) actives formed by matching the new symbols in newsi against
435 all specs currently listed in topSpecs
436
437 (3) actives formed by matching the new symbols in newsi against
438 the new specs in specList
439
440 This is necessary in order to maintain the invariant that
441 Actives contains all bindings generated by matching ALL specs in
442 topSpecs against ALL symbols in topSpecs (that is, a cross
443 product of ALL known specs against ALL known symbols).
444 */
445 /* Case (1) */
446 for (ts = topSpecs; ts; ts = ts->next) {
447 if (ts->seginfo)
448 generate_and_add_actives( specList, newts,
449 ts->seginfo, ts );
450 }
sewardj6b9cc872006-10-17 01:39:30 +0000451
sewardj0ec07f32006-01-12 12:32:32 +0000452 /* Case (2) */
453 for (ts = topSpecs; ts; ts = ts->next) {
454 generate_and_add_actives( ts->specs, ts,
455 newsi, newts );
456 }
457
458 /* Case (3) */
459 generate_and_add_actives( specList, newts,
460 newsi, newts );
461
462 /* Finally, add the new TopSpec. */
463 newts->next = topSpecs;
464 topSpecs = newts;
465
466 if (VG_(clo_trace_redir))
sewardjb8b79ad2008-03-03 01:35:41 +0000467 show_redir_state("after VG_(redir_notify_new_DebugInfo)");
sewardj0ec07f32006-01-12 12:32:32 +0000468}
469
470#undef N_DEMANGLED
471
472
473/* Do one element of the basic cross product: add to the active set,
474 all matches resulting from comparing all the given specs against
475 all the symbols in the given seginfo. If a conflicting binding
476 would thereby arise, don't add it, but do complain. */
477
478static
479void generate_and_add_actives (
480 /* spec list and the owning TopSpec */
481 Spec* specs,
482 TopSpec* parent_spec,
483 /* seginfo and the owning TopSpec */
sewardjb8b79ad2008-03-03 01:35:41 +0000484 DebugInfo* di,
sewardj0ec07f32006-01-12 12:32:32 +0000485 TopSpec* parent_sym
486 )
487{
488 Spec* sp;
sewardjb8b79ad2008-03-03 01:35:41 +0000489 Bool anyMark, isText;
sewardj0ec07f32006-01-12 12:32:32 +0000490 Active act;
491 Int nsyms, i;
492 Addr sym_addr;
493 HChar* sym_name;
494
sewardjdf24cf12007-11-16 18:32:40 +0000495 /* First figure out which of the specs match the seginfo's soname.
496 Also clear the 'done' bits, so that after the main loop below
497 tell which of the Specs really did get done. */
sewardj0ec07f32006-01-12 12:32:32 +0000498 anyMark = False;
499 for (sp = specs; sp; sp = sp->next) {
sewardjdf24cf12007-11-16 18:32:40 +0000500 sp->done = False;
sewardj0ec07f32006-01-12 12:32:32 +0000501 sp->mark = VG_(string_match)( sp->from_sopatt,
sewardjb8b79ad2008-03-03 01:35:41 +0000502 VG_(seginfo_soname)(di) );
sewardj0ec07f32006-01-12 12:32:32 +0000503 anyMark = anyMark || sp->mark;
504 }
505
506 /* shortcut: if none of the sonames match, there will be no bindings. */
507 if (!anyMark)
508 return;
509
510 /* Iterate outermost over the symbols in the seginfo, in the hope
511 of trashing the caches less. */
sewardjb8b79ad2008-03-03 01:35:41 +0000512 nsyms = VG_(seginfo_syms_howmany)( di );
sewardj0ec07f32006-01-12 12:32:32 +0000513 for (i = 0; i < nsyms; i++) {
sewardjb8b79ad2008-03-03 01:35:41 +0000514 VG_(seginfo_syms_getidx)( di, i,
515 &sym_addr, NULL, NULL, &sym_name, &isText );
516
517 /* ignore data symbols */
518 if (!isText)
519 continue;
sewardj6b9cc872006-10-17 01:39:30 +0000520
521 /* On AIX, we cannot redirect calls to a so-called glink
522 function for reasons which are not obvious - something to do
523 with saving r2 across the call. Not a problem, as we don't
524 want to anyway; presumably it is the target of the glink we
525 need to redirect. Hence just spot them and ignore them.
526 They are always of a very specific (more or less
527 ABI-mandated) form. */
528 if (is_aix5_glink_idiom(sym_addr))
529 continue;
530
sewardj0ec07f32006-01-12 12:32:32 +0000531 for (sp = specs; sp; sp = sp->next) {
532 if (!sp->mark)
533 continue; /* soname doesn't match */
534 if (VG_(string_match)( sp->from_fnpatt, sym_name )) {
535 /* got a new binding. Add to collection. */
536 act.from_addr = sym_addr;
537 act.to_addr = sp->to_addr;
538 act.parent_spec = parent_spec;
539 act.parent_sym = parent_sym;
540 act.isWrap = sp->isWrap;
sewardjdf24cf12007-11-16 18:32:40 +0000541 sp->done = True;
sewardj0ec07f32006-01-12 12:32:32 +0000542 maybe_add_active( act );
543 }
sewardjdf24cf12007-11-16 18:32:40 +0000544 } /* for (sp = specs; sp; sp = sp->next) */
545 } /* for (i = 0; i < nsyms; i++) */
546
547 /* Now, finally, look for Specs which were marked to be done, but
548 didn't get matched. If any such are mandatory we must abort the
549 system at this point. */
550 for (sp = specs; sp; sp = sp->next) {
551 if (!sp->mark)
552 continue;
553 if (sp->mark && (!sp->done) && sp->mandatory)
554 break;
555 }
556 if (sp) {
557 HChar* v = "valgrind: ";
558 vg_assert(sp->mark);
559 vg_assert(!sp->done);
560 vg_assert(sp->mandatory);
561 VG_(printf)("\n");
562 VG_(printf)(
563 "%sFatal error at startup: a function redirection\n", v);
564 VG_(printf)(
565 "%swhich is mandatory for this platform-tool combination\n", v);
566 VG_(printf)(
567 "%scannot be set up. Details of the redirection are:\n", v);
568 VG_(printf)(
569 "%s\n", v);
570 VG_(printf)(
571 "%sA must-be-redirected function\n", v);
572 VG_(printf)(
573 "%swhose name matches the pattern: %s\n", v, sp->from_fnpatt);
574 VG_(printf)(
575 "%sin an object with soname matching: %s\n", v, sp->from_sopatt);
576 VG_(printf)(
577 "%swas not found whilst processing\n", v);
578 VG_(printf)(
sewardjb8b79ad2008-03-03 01:35:41 +0000579 "%ssymbols from the object with soname: %s\n", v, VG_(seginfo_soname)(di));
sewardjdf24cf12007-11-16 18:32:40 +0000580 VG_(printf)(
581 "%s\n", v);
582 VG_(printf)(
583 "%s%s\n", v, sp->mandatory);
584 VG_(printf)(
585 "%s\n", v);
586 VG_(printf)(
587 "%sCannot continue -- exiting now. Sorry.\n", v);
588 VG_(printf)("\n");
589 VG_(exit)(1);
sewardj0ec07f32006-01-12 12:32:32 +0000590 }
591}
592
593
594/* Add an act (passed by value; is copied here) and deal with
595 conflicting bindings. */
596static void maybe_add_active ( Active act )
597{
598 HChar* what = NULL;
599 Active* old;
600
601 /* Complain and ignore manifestly bogus 'from' addresses.
602
603 Kludge: because this can get called befor the trampoline area (a
604 bunch of magic 'to' addresses) has its ownership changed from V
605 to C, we can't check the 'to' address similarly. Sigh.
606
607 amd64-linux hack: the vsysinfo pages appear to have no
608 permissions
609 ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0
610 so skip the check for them. */
611 if (!is_plausible_guest_addr(act.from_addr)
612# if defined(VGP_amd64_linux)
613 && act.from_addr != 0xFFFFFFFFFF600000ULL
614 && act.from_addr != 0xFFFFFFFFFF600400ULL
615# endif
616 ) {
617 what = "redirection from-address is in non-executable area";
618 goto bad;
619 }
620
njne2a9ad32007-09-17 05:30:48 +0000621 old = VG_(OSetGen_Lookup)( activeSet, &act.from_addr );
sewardj0ec07f32006-01-12 12:32:32 +0000622 if (old) {
623 /* Dodgy. Conflicting binding. */
624 vg_assert(old->from_addr == act.from_addr);
625 if (old->to_addr != act.to_addr) {
626 /* we have to ignore it -- otherwise activeSet would contain
627 conflicting bindings. */
628 what = "new redirection conflicts with existing -- ignoring it";
629 goto bad;
njnd9109c62005-06-26 04:49:25 +0000630 } else {
sewardj0ec07f32006-01-12 12:32:32 +0000631 /* This appears to be a duplicate of an existing binding.
632 Safe(ish) -- ignore. */
633 /* XXXXXXXXXXX COMPLAIN if new and old parents differ */
tom748a1312005-04-02 15:53:01 +0000634 }
njnd9109c62005-06-26 04:49:25 +0000635 } else {
njne2a9ad32007-09-17 05:30:48 +0000636 Active* a = VG_(OSetGen_AllocNode)(activeSet, sizeof(Active));
sewardj0ec07f32006-01-12 12:32:32 +0000637 vg_assert(a);
638 *a = act;
njne2a9ad32007-09-17 05:30:48 +0000639 VG_(OSetGen_Insert)(activeSet, a);
sewardj0ec07f32006-01-12 12:32:32 +0000640 /* Now that a new from->to redirection is in force, we need to
641 get rid of any translations intersecting 'from' in order that
642 they get redirected to 'to'. So discard them. Just for
643 paranoia (but, I believe, unnecessarily), discard 'to' as
644 well. */
645 VG_(discard_translations)( (Addr64)act.from_addr, 1,
sewardjb8b79ad2008-03-03 01:35:41 +0000646 "redir_new_DebugInfo(from_addr)");
sewardj0ec07f32006-01-12 12:32:32 +0000647 VG_(discard_translations)( (Addr64)act.to_addr, 1,
sewardjb8b79ad2008-03-03 01:35:41 +0000648 "redir_new_DebugInfo(to_addr)");
sewardj0ec07f32006-01-12 12:32:32 +0000649 }
650 return;
651
652 bad:
653 vg_assert(what);
654 if (VG_(clo_verbosity) > 1) {
655 VG_(message)(Vg_UserMsg, "WARNING: %s", what);
656 show_active( " new: ", &act);
njnd9109c62005-06-26 04:49:25 +0000657 }
tom748a1312005-04-02 15:53:01 +0000658}
659
njnd9109c62005-06-26 04:49:25 +0000660
sewardjb8b79ad2008-03-03 01:35:41 +0000661/* Notify m_redir of the deletion of a DebugInfo. This is relatively
sewardj0ec07f32006-01-12 12:32:32 +0000662 simple -- just get rid of all actives derived from it, and free up
663 the associated list elements. */
664
sewardjb8b79ad2008-03-03 01:35:41 +0000665void VG_(redir_notify_delete_DebugInfo)( DebugInfo* delsi )
sewardj0ec07f32006-01-12 12:32:32 +0000666{
667 TopSpec* ts;
668 TopSpec* tsPrev;
669 Spec* sp;
670 Spec* sp_next;
671 OSet* tmpSet;
672 Active* act;
673 Bool delMe;
njne2a9ad32007-09-17 05:30:48 +0000674 Addr addr;
sewardj0ec07f32006-01-12 12:32:32 +0000675
676 vg_assert(delsi);
677
678 /* Search for it, and make tsPrev point to the previous entry, if
679 any. */
680 tsPrev = NULL;
681 ts = topSpecs;
682 while (True) {
683 if (ts == NULL) break;
684 if (ts->seginfo == delsi) break;
685 tsPrev = ts;
686 ts = ts->next;
687 }
688
sewardjb8b79ad2008-03-03 01:35:41 +0000689 vg_assert(ts); /* else we don't have the deleted DebugInfo */
sewardj0ec07f32006-01-12 12:32:32 +0000690 vg_assert(ts->seginfo == delsi);
691
692 /* Traverse the actives, copying the addresses of those we intend
693 to delete into tmpSet. */
sewardjb8b79ad2008-03-03 01:35:41 +0000694 tmpSet = VG_(OSetWord_Create)(dinfo_zalloc, dinfo_free);
sewardj0ec07f32006-01-12 12:32:32 +0000695
696 ts->mark = True;
697
njne2a9ad32007-09-17 05:30:48 +0000698 VG_(OSetGen_ResetIter)( activeSet );
699 while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
sewardj0ec07f32006-01-12 12:32:32 +0000700 delMe = act->parent_spec != NULL
701 && act->parent_sym != NULL
702 && act->parent_spec->seginfo != NULL
703 && act->parent_sym->seginfo != NULL
704 && (act->parent_spec->mark || act->parent_sym->mark);
705
706 /* While we're at it, a bit of paranoia: delete any actives
sewardje6647f42006-03-12 00:39:19 +0000707 which don't have both feet in valid client executable areas.
708 But don't delete hardwired-at-startup ones; these are denoted
709 by having parent_spec or parent_sym being NULL. */
710 if ( (!delMe)
711 && act->parent_spec != NULL
712 && act->parent_sym != NULL ) {
713 if (!is_plausible_guest_addr(act->from_addr))
714 delMe = True;
715 if (!is_plausible_guest_addr(act->to_addr))
716 delMe = True;
sewardj0ec07f32006-01-12 12:32:32 +0000717 }
718
719 if (delMe) {
njne2a9ad32007-09-17 05:30:48 +0000720 VG_(OSetWord_Insert)( tmpSet, act->from_addr );
sewardj0ec07f32006-01-12 12:32:32 +0000721 /* While we have our hands on both the 'from' and 'to'
722 of this Active, do paranoid stuff with tt/tc. */
723 VG_(discard_translations)( (Addr64)act->from_addr, 1,
sewardjb8b79ad2008-03-03 01:35:41 +0000724 "redir_del_DebugInfo(from_addr)");
sewardj0ec07f32006-01-12 12:32:32 +0000725 VG_(discard_translations)( (Addr64)act->to_addr, 1,
sewardjb8b79ad2008-03-03 01:35:41 +0000726 "redir_del_DebugInfo(to_addr)");
sewardj0ec07f32006-01-12 12:32:32 +0000727 }
728 }
729
njne2a9ad32007-09-17 05:30:48 +0000730 /* Now traverse tmpSet, deleting corresponding elements in activeSet. */
731 VG_(OSetWord_ResetIter)( tmpSet );
732 while ( VG_(OSetWord_Next)(tmpSet, &addr) ) {
733 act = VG_(OSetGen_Remove)( activeSet, &addr );
sewardj0ec07f32006-01-12 12:32:32 +0000734 vg_assert(act);
njne2a9ad32007-09-17 05:30:48 +0000735 VG_(OSetGen_FreeNode)( activeSet, act );
sewardj0ec07f32006-01-12 12:32:32 +0000736 }
737
njne2a9ad32007-09-17 05:30:48 +0000738 VG_(OSetWord_Destroy)( tmpSet );
sewardj0ec07f32006-01-12 12:32:32 +0000739
740 /* The Actives set is now cleaned up. Free up this TopSpec and
741 everything hanging off it. */
742 for (sp = ts->specs; sp; sp = sp_next) {
sewardjb8b79ad2008-03-03 01:35:41 +0000743 if (sp->from_sopatt) dinfo_free(sp->from_sopatt);
744 if (sp->from_fnpatt) dinfo_free(sp->from_fnpatt);
sewardj0ec07f32006-01-12 12:32:32 +0000745 sp_next = sp->next;
sewardjb8b79ad2008-03-03 01:35:41 +0000746 dinfo_free(sp);
sewardj0ec07f32006-01-12 12:32:32 +0000747 }
748
749 if (tsPrev == NULL) {
750 /* first in list */
751 topSpecs = ts->next;
njnd9109c62005-06-26 04:49:25 +0000752 } else {
sewardj0ec07f32006-01-12 12:32:32 +0000753 tsPrev->next = ts->next;
sewardjcbdddcf2005-03-10 23:23:45 +0000754 }
sewardjb8b79ad2008-03-03 01:35:41 +0000755 dinfo_free(ts);
sewardjcbdddcf2005-03-10 23:23:45 +0000756
sewardj0ec07f32006-01-12 12:32:32 +0000757 if (VG_(clo_trace_redir))
sewardjb8b79ad2008-03-03 01:35:41 +0000758 show_redir_state("after VG_(redir_notify_delete_DebugInfo)");
sewardjcbdddcf2005-03-10 23:23:45 +0000759}
760
sewardj0ec07f32006-01-12 12:32:32 +0000761
762/*------------------------------------------------------------*/
763/*--- QUERIES (really the whole point of this module) ---*/
764/*------------------------------------------------------------*/
765
766/* This is the crucial redirection function. It answers the question:
767 should this code address be redirected somewhere else? It's used
768 just before translating a basic block. */
769Addr VG_(redir_do_lookup) ( Addr orig, Bool* isWrap )
sewardjcbdddcf2005-03-10 23:23:45 +0000770{
njne2a9ad32007-09-17 05:30:48 +0000771 Active* r = VG_(OSetGen_Lookup)(activeSet, &orig);
sewardjcbdddcf2005-03-10 23:23:45 +0000772 if (r == NULL)
sewardj0ec07f32006-01-12 12:32:32 +0000773 return orig;
sewardjcbdddcf2005-03-10 23:23:45 +0000774
775 vg_assert(r->to_addr != 0);
sewardj0ec07f32006-01-12 12:32:32 +0000776 if (isWrap)
777 *isWrap = r->isWrap;
sewardjcbdddcf2005-03-10 23:23:45 +0000778 return r->to_addr;
779}
780
sewardj0ec07f32006-01-12 12:32:32 +0000781
782/*------------------------------------------------------------*/
783/*--- INITIALISATION ---*/
784/*------------------------------------------------------------*/
785
786/* Add a never-delete-me Active. */
787
788__attribute__((unused)) /* only used on amd64 */
789static void add_hardwired_active ( Addr from, Addr to )
njn8a96ec52005-10-15 15:48:52 +0000790{
sewardj0ec07f32006-01-12 12:32:32 +0000791 Active act;
792 act.from_addr = from;
793 act.to_addr = to;
794 act.parent_spec = NULL;
795 act.parent_sym = NULL;
796 act.isWrap = False;
797 maybe_add_active( act );
njn8a96ec52005-10-15 15:48:52 +0000798}
799
sewardj0ec07f32006-01-12 12:32:32 +0000800
801/* Add a never-delete-me Spec. This is a bit of a kludge. On the
802 assumption that this is called only at startup, only handle the
803 case where topSpecs is completely empty, or if it isn't, it has
804 just one entry and that is the one with NULL seginfo -- that is the
805 entry that holds these initial specs. */
806
807__attribute__((unused)) /* not used on all platforms */
sewardjdf24cf12007-11-16 18:32:40 +0000808static void add_hardwired_spec ( HChar* sopatt, HChar* fnpatt,
809 Addr to_addr,
810 HChar* mandatory )
njn8a96ec52005-10-15 15:48:52 +0000811{
sewardjb8b79ad2008-03-03 01:35:41 +0000812 Spec* spec = dinfo_zalloc(sizeof(Spec));
sewardj0ec07f32006-01-12 12:32:32 +0000813 vg_assert(spec);
814
815 if (topSpecs == NULL) {
sewardjb8b79ad2008-03-03 01:35:41 +0000816 topSpecs = dinfo_zalloc(sizeof(TopSpec));
sewardj0ec07f32006-01-12 12:32:32 +0000817 vg_assert(topSpecs);
sewardjdf24cf12007-11-16 18:32:40 +0000818 /* symtab_zalloc sets all fields to zero */
sewardj0ec07f32006-01-12 12:32:32 +0000819 }
820
821 vg_assert(topSpecs != NULL);
822 vg_assert(topSpecs->next == NULL);
823 vg_assert(topSpecs->seginfo == NULL);
sewardjdf24cf12007-11-16 18:32:40 +0000824 /* FIXED PARTS */
sewardj0ec07f32006-01-12 12:32:32 +0000825 spec->from_sopatt = sopatt;
826 spec->from_fnpatt = fnpatt;
827 spec->to_addr = to_addr;
828 spec->isWrap = False;
sewardjdf24cf12007-11-16 18:32:40 +0000829 spec->mandatory = mandatory;
830 /* VARIABLE PARTS */
sewardj0ec07f32006-01-12 12:32:32 +0000831 spec->mark = False; /* not significant */
sewardjdf24cf12007-11-16 18:32:40 +0000832 spec->done = False; /* not significant */
sewardj0ec07f32006-01-12 12:32:32 +0000833
834 spec->next = topSpecs->specs;
835 topSpecs->specs = spec;
njn8a96ec52005-10-15 15:48:52 +0000836}
837
njn8a96ec52005-10-15 15:48:52 +0000838
sewardj0ec07f32006-01-12 12:32:32 +0000839/* Initialise the redir system, and create the initial Spec list and
840 for amd64-linux a couple of permanent active mappings. The initial
841 Specs are not converted into Actives yet, on the (checked)
sewardjb8b79ad2008-03-03 01:35:41 +0000842 assumption that no DebugInfos have so far been created, and so when
sewardj0ec07f32006-01-12 12:32:32 +0000843 they are created, that will happen. */
844
845void VG_(redir_initialise) ( void )
846{
sewardjb8b79ad2008-03-03 01:35:41 +0000847 // Assert that there are no DebugInfos so far
sewardj0ec07f32006-01-12 12:32:32 +0000848 vg_assert( VG_(next_seginfo)(NULL) == NULL );
849
850 // Initialise active mapping.
njne2a9ad32007-09-17 05:30:48 +0000851 activeSet = VG_(OSetGen_Create)(offsetof(Active, from_addr),
852 NULL, // Use fast comparison
sewardjb8b79ad2008-03-03 01:35:41 +0000853 dinfo_zalloc,
854 dinfo_free);
sewardj0ec07f32006-01-12 12:32:32 +0000855
856 // The rest of this function just adds initial Specs.
857
858# if defined(VGP_x86_linux)
sewardj6a443b22005-11-20 19:37:54 +0000859 /* If we're using memcheck, use this intercept right from the
860 start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */
861 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
sewardj0ec07f32006-01-12 12:32:32 +0000862 add_hardwired_spec(
863 "ld-linux.so.2", "index",
sewardjdf24cf12007-11-16 18:32:40 +0000864 (Addr)&VG_(x86_linux_REDIR_FOR_index),
865 NULL
sewardj0ec07f32006-01-12 12:32:32 +0000866 );
sewardj6a443b22005-11-20 19:37:54 +0000867 }
sewardjb9bce632005-06-21 01:41:34 +0000868
sewardj0ec07f32006-01-12 12:32:32 +0000869# elif defined(VGP_amd64_linux)
njnd1af0032005-05-29 17:01:48 +0000870 /* Redirect vsyscalls to local versions */
sewardj0ec07f32006-01-12 12:32:32 +0000871 add_hardwired_active(
sewardjb9bce632005-06-21 01:41:34 +0000872 0xFFFFFFFFFF600000ULL,
873 (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday)
874 );
sewardj0ec07f32006-01-12 12:32:32 +0000875 add_hardwired_active(
tomf5db3b62005-06-21 13:26:17 +0000876 0xFFFFFFFFFF600400ULL,
sewardjb9bce632005-06-21 01:41:34 +0000877 (Addr)&VG_(amd64_linux_REDIR_FOR_vtime)
878 );
879
sewardj0ec07f32006-01-12 12:32:32 +0000880# elif defined(VGP_ppc32_linux)
sewardj96fcfc82005-11-18 21:12:52 +0000881 /* If we're using memcheck, use these intercepts right from
882 the start, otherwise ld.so makes a lot of noise. */
883 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
sewardj0fd30492007-11-16 19:39:49 +0000884
885 static HChar* croakage = "Possible fix: install glibc's debuginfo "
886 "package on this machine.";
887
sewardj5092a972007-11-16 18:45:40 +0000888 /* this is mandatory - can't sanely continue without it */
sewardj0ec07f32006-01-12 12:32:32 +0000889 add_hardwired_spec(
890 "ld.so.1", "strlen",
sewardjdf24cf12007-11-16 18:32:40 +0000891 (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen),
sewardj5092a972007-11-16 18:45:40 +0000892 croakage
sewardj96fcfc82005-11-18 21:12:52 +0000893 );
sewardj0ec07f32006-01-12 12:32:32 +0000894 add_hardwired_spec(
sewardjd5a30a42006-02-09 10:29:43 +0000895 "ld.so.1", "strcmp",
sewardjdf24cf12007-11-16 18:32:40 +0000896 (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp),
sewardj5092a972007-11-16 18:45:40 +0000897 NULL /* not mandatory - so why bother at all? */
898 /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
sewardj96fcfc82005-11-18 21:12:52 +0000899 );
sewardjcd8c95a2006-08-25 11:48:38 +0000900 add_hardwired_spec(
901 "ld.so.1", "index",
sewardjdf24cf12007-11-16 18:32:40 +0000902 (Addr)&VG_(ppc32_linux_REDIR_FOR_strchr),
sewardj5092a972007-11-16 18:45:40 +0000903 NULL /* not mandatory - so why bother at all? */
904 /* glibc-2.6.1 (openSUSE 10.3, ppc32) seems fine without it */
sewardjcd8c95a2006-08-25 11:48:38 +0000905 );
sewardj96fcfc82005-11-18 21:12:52 +0000906 }
sewardjb9bce632005-06-21 01:41:34 +0000907
sewardj0ec07f32006-01-12 12:32:32 +0000908# elif defined(VGP_ppc64_linux)
sewardjf0915fc2006-01-05 14:07:04 +0000909 /* If we're using memcheck, use these intercepts right from
910 the start, otherwise ld.so makes a lot of noise. */
911 if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
912
sewardj0fd30492007-11-16 19:39:49 +0000913 static HChar* croakage = "Possible fix: install glibc's debuginfo "
914 "package on this machine.";
915
916 /* this is mandatory - can't sanely continue without it */
sewardj1a85f4f2006-01-12 21:15:35 +0000917 add_hardwired_spec(
918 "ld64.so.1", "strlen",
sewardjdf24cf12007-11-16 18:32:40 +0000919 (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ),
sewardj0fd30492007-11-16 19:39:49 +0000920 croakage
sewardjdf24cf12007-11-16 18:32:40 +0000921 );
sewardjf0915fc2006-01-05 14:07:04 +0000922
sewardj1a85f4f2006-01-12 21:15:35 +0000923 add_hardwired_spec(
924 "ld64.so.1", "index",
sewardjdf24cf12007-11-16 18:32:40 +0000925 (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strchr) ),
sewardj0fd30492007-11-16 19:39:49 +0000926 NULL /* not mandatory - so why bother at all? */
927 /* glibc-2.5 (FC6, ppc64) seems fine without it */
sewardjdf24cf12007-11-16 18:32:40 +0000928 );
sewardj1a85f4f2006-01-12 21:15:35 +0000929
sewardjf0915fc2006-01-05 14:07:04 +0000930 }
sewardj2c48c7b2005-11-29 13:05:56 +0000931
sewardj6b9cc872006-10-17 01:39:30 +0000932# elif defined(VGP_ppc32_aix5)
933 /* nothing so far */
934
935# elif defined(VGP_ppc64_aix5)
936 /* nothing so far */
937
sewardj0ec07f32006-01-12 12:32:32 +0000938# else
939# error Unknown platform
940# endif
941
942 if (VG_(clo_trace_redir))
943 show_redir_state("after VG_(redir_initialise)");
njnd1af0032005-05-29 17:01:48 +0000944}
sewardjcbdddcf2005-03-10 23:23:45 +0000945
njn16eeb4e2005-06-16 03:56:58 +0000946
sewardj0ec07f32006-01-12 12:32:32 +0000947/*------------------------------------------------------------*/
948/*--- MISC HELPERS ---*/
949/*------------------------------------------------------------*/
950
sewardjb8b79ad2008-03-03 01:35:41 +0000951static void* dinfo_zalloc(SizeT n) {
sewardjdf24cf12007-11-16 18:32:40 +0000952 void* p;
953 vg_assert(n > 0);
sewardjb8b79ad2008-03-03 01:35:41 +0000954 p = VG_(arena_malloc)(VG_AR_DINFO, n);
sewardjdf24cf12007-11-16 18:32:40 +0000955 tl_assert(p);
956 VG_(memset)(p, 0, n);
957 return p;
njn16eeb4e2005-06-16 03:56:58 +0000958}
959
sewardjb8b79ad2008-03-03 01:35:41 +0000960static void dinfo_free(void* p) {
sewardjdf24cf12007-11-16 18:32:40 +0000961 tl_assert(p);
sewardjb8b79ad2008-03-03 01:35:41 +0000962 return VG_(arena_free)(VG_AR_DINFO, p);
njn16eeb4e2005-06-16 03:56:58 +0000963}
964
sewardjb8b79ad2008-03-03 01:35:41 +0000965static HChar* dinfo_strdup(HChar* str)
njnbc6d84d2005-06-19 18:58:03 +0000966{
sewardjb8b79ad2008-03-03 01:35:41 +0000967 return VG_(arena_strdup)(VG_AR_DINFO, str);
njnbc6d84d2005-06-19 18:58:03 +0000968}
969
sewardj0ec07f32006-01-12 12:32:32 +0000970/* Really this should be merged with translations_allowable_from_seg
971 in m_translate. */
972static Bool is_plausible_guest_addr(Addr a)
njn16eeb4e2005-06-16 03:56:58 +0000973{
sewardj6b9cc872006-10-17 01:39:30 +0000974 NSegment const* seg = VG_(am_find_nsegment)(a);
sewardj0ec07f32006-01-12 12:32:32 +0000975 return seg != NULL
976 && (seg->kind == SkAnonC || seg->kind == SkFileC)
977 && (seg->hasX || seg->hasR); /* crude x86-specific hack */
978}
979
sewardj6b9cc872006-10-17 01:39:30 +0000980/* A function which spots AIX 'glink' functions. A 'glink' function
981 is a stub function which has something to do with AIX-style dynamic
982 linking, and jumps to the real target (with which it typically
983 shares the same name). See also comment where this function is
984 used (above). */
985static Bool is_aix5_glink_idiom ( Addr sym_addr )
986{
987# if defined(VGP_ppc32_aix5)
988 UInt* w = (UInt*)sym_addr;
989 if (VG_IS_4_ALIGNED(w)
990 && is_plausible_guest_addr((Addr)(w+0))
991 && is_plausible_guest_addr((Addr)(w+6))
992 && (w[0] & 0xFFFF0000) == 0x81820000 /* lwz r12,func@toc(r2) */
993 && w[1] == 0x90410014 /* stw r2,20(r1) */
994 && w[2] == 0x800c0000 /* lwz r0,0(r12) */
995 && w[3] == 0x804c0004 /* lwz r2,4(r12) */
996 && w[4] == 0x7c0903a6 /* mtctr r0 */
997 && w[5] == 0x4e800420 /* bctr */
998 && w[6] == 0x00000000 /* illegal */)
999 return True;
1000# elif defined(VGP_ppc64_aix5)
1001 UInt* w = (UInt*)sym_addr;
1002 if (VG_IS_4_ALIGNED(w)
1003 && is_plausible_guest_addr((Addr)(w+0))
1004 && is_plausible_guest_addr((Addr)(w+6))
1005 && (w[0] & 0xFFFF0000) == 0xE9820000 /* ld r12,func@toc(r2) */
1006 && w[1] == 0xF8410028 /* std r2,40(r1) */
1007 && w[2] == 0xE80C0000 /* ld r0,0(r12) */
1008 && w[3] == 0xE84C0008 /* ld r2,8(r12) */
1009 && w[4] == 0x7c0903a6 /* mtctr r0 */
1010 && w[5] == 0x4e800420 /* bctr */
1011 && w[6] == 0x00000000 /* illegal */)
1012 return True;
1013# endif
1014 return False;
1015}
sewardj0ec07f32006-01-12 12:32:32 +00001016
1017/*------------------------------------------------------------*/
1018/*--- NOTIFY-ON-LOAD FUNCTIONS ---*/
1019/*------------------------------------------------------------*/
1020
sewardja672ea32006-04-29 18:03:14 +00001021static
1022void handle_maybe_load_notifier( const UChar* soname,
1023 HChar* symbol, Addr addr )
sewardj0ec07f32006-01-12 12:32:32 +00001024{
sewardja672ea32006-04-29 18:03:14 +00001025# if defined(VGP_x86_linux)
1026 /* x86-linux only: if we see _dl_sysinfo_int80, note its address.
1027 See comment on declaration of VG_(client__dl_sysinfo_int80) for
1028 the reason. As far as I can tell, the relevant symbol is always
1029 in object with soname "ld-linux.so.2". */
1030 if (symbol && symbol[0] == '_'
1031 && 0 == VG_(strcmp)(symbol, "_dl_sysinfo_int80")
1032 && 0 == VG_(strcmp)(soname, "ld-linux.so.2")) {
1033 if (VG_(client__dl_sysinfo_int80) == 0)
1034 VG_(client__dl_sysinfo_int80) = addr;
1035 }
1036# endif
1037
1038 /* Normal load-notifier handling after here. First, ignore all
1039 symbols lacking the right prefix. */
sewardj0ec07f32006-01-12 12:32:32 +00001040 if (0 != VG_(strncmp)(symbol, VG_NOTIFY_ON_LOAD_PREFIX,
1041 VG_NOTIFY_ON_LOAD_PREFIX_LEN))
1042 /* Doesn't have the right prefix */
1043 return;
1044
1045 if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0)
1046 VG_(client___libc_freeres_wrapper) = addr;
njn16eeb4e2005-06-16 03:56:58 +00001047 else
1048 vg_assert2(0, "unrecognised load notification function: %s", symbol);
1049}
1050
sewardj0ec07f32006-01-12 12:32:32 +00001051
1052/*------------------------------------------------------------*/
1053/*--- SANITY/DEBUG ---*/
1054/*------------------------------------------------------------*/
1055
1056static void show_spec ( HChar* left, Spec* spec )
njn16eeb4e2005-06-16 03:56:58 +00001057{
sewardj0ec07f32006-01-12 12:32:32 +00001058 VG_(message)(Vg_DebugMsg,
sewardj6b9cc872006-10-17 01:39:30 +00001059 "%s%25s %30s %s-> 0x%08llx",
sewardj0ec07f32006-01-12 12:32:32 +00001060 left,
1061 spec->from_sopatt, spec->from_fnpatt,
1062 spec->isWrap ? "W" : "R",
1063 (ULong)spec->to_addr );
njn16eeb4e2005-06-16 03:56:58 +00001064}
1065
sewardj0ec07f32006-01-12 12:32:32 +00001066static void show_active ( HChar* left, Active* act )
njn16eeb4e2005-06-16 03:56:58 +00001067{
sewardj0ec07f32006-01-12 12:32:32 +00001068 Bool ok;
1069 HChar name1[64] = "";
1070 HChar name2[64] = "";
1071 name1[0] = name2[0] = 0;
1072 ok = VG_(get_fnname_w_offset)(act->from_addr, name1, 64);
1073 if (!ok) VG_(strcpy)(name1, "???");
1074 ok = VG_(get_fnname_w_offset)(act->to_addr, name2, 64);
1075 if (!ok) VG_(strcpy)(name2, "???");
1076
sewardj6b9cc872006-10-17 01:39:30 +00001077 VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> 0x%08llx %s",
sewardj0ec07f32006-01-12 12:32:32 +00001078 left,
1079 (ULong)act->from_addr, name1,
1080 act->isWrap ? "W" : "R",
1081 (ULong)act->to_addr, name2 );
njn16eeb4e2005-06-16 03:56:58 +00001082}
1083
sewardj0ec07f32006-01-12 12:32:32 +00001084static void show_redir_state ( HChar* who )
njn16eeb4e2005-06-16 03:56:58 +00001085{
sewardj0ec07f32006-01-12 12:32:32 +00001086 TopSpec* ts;
1087 Spec* sp;
1088 Active* act;
1089 VG_(message)(Vg_DebugMsg, "<<");
1090 VG_(message)(Vg_DebugMsg, " ------ REDIR STATE %s ------", who);
1091 for (ts = topSpecs; ts; ts = ts->next) {
1092 VG_(message)(Vg_DebugMsg,
1093 " TOPSPECS of soname %s",
1094 ts->seginfo ? (HChar*)VG_(seginfo_soname)(ts->seginfo)
1095 : "(hardwired)" );
1096 for (sp = ts->specs; sp; sp = sp->next)
1097 show_spec(" ", sp);
1098 }
1099 VG_(message)(Vg_DebugMsg, " ------ ACTIVE ------");
njne2a9ad32007-09-17 05:30:48 +00001100 VG_(OSetGen_ResetIter)( activeSet );
1101 while ( (act = VG_(OSetGen_Next)(activeSet)) ) {
sewardj0ec07f32006-01-12 12:32:32 +00001102 show_active(" ", act);
1103 }
1104
1105 VG_(message)(Vg_DebugMsg, ">>");
njn16eeb4e2005-06-16 03:56:58 +00001106}
1107
njnc0ae7052005-08-25 22:55:19 +00001108/*--------------------------------------------------------------------*/
1109/*--- end ---*/
1110/*--------------------------------------------------------------------*/