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