void VG_(setup_code_redirect_table) ( void ) { // Initialise resolved_redirs list. resolved_redirs = VG_(OSet_Create)(offsetof(CodeRedirect, from_addr), NULL, // Use fast comparison symtab_alloc, symtab_free); #if defined(VGP_x86_linux) /* Redirect _dl_sysinfo_int80, which is glibc's default system call routine, to our copy so that the special sysinfo unwind hack in m_stacktrace.c will kick in. */ add_redirect_sym_to_addr( "soname:ld-linux.so.2", "_dl_sysinfo_int80", (Addr)&VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80) ); /* If we're using memcheck, use this intercept right from the start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { add_redirect_sym_to_addr( "soname:ld-linux.so.2", "index", (Addr)&VG_(x86_linux_REDIR_FOR_index) ); } #elif defined(VGP_amd64_linux) /* Redirect vsyscalls to local versions */ add_redirect_addr_to_addr( 0xFFFFFFFFFF600000ULL, (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday) ); add_redirect_addr_to_addr( 0xFFFFFFFFFF600400ULL, (Addr)&VG_(amd64_linux_REDIR_FOR_vtime) ); #elif defined(VGP_ppc32_linux) /* If we're using memcheck, use these intercepts right from the start, otherwise ld.so makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { add_redirect_sym_to_addr( "soname:ld.so.1", "strlen", (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen) ); add_redirect_sym_to_addr( "soname:ld.so.1", "strcmp", (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp) ); } #else # error Unknown platform #endif }
// Nb: this can change the string pointed to by 'symbol'. static void handle_replacement_function( Char* symbol, Addr addr ) { Bool ok; Int len = VG_(strlen)(symbol) + 1 - VG_REPLACE_FUNCTION_PREFIX_LEN; Char *lib = VG_(arena_malloc)(VG_AR_SYMTAB, len+8); Char *func; // Put "soname:" at the start of lib VG_(strcpy)(lib, "soname:"); ok = Z_decode(symbol, lib+7, len); if (ok) { // lib is "soname:<libname>:<fnname>". Split the string at the 2nd ':'. func = lib + VG_(strlen)(lib)-1; while(*func != ':') func--; *func = '\0'; func++; // Move past the '\0' // Now lib is "soname:<libname>" and func is "<fnname>". if (0) VG_(printf)("lib A%sZ, func A%sZ\n", lib, func); add_redirect_sym_to_addr(lib, func, addr); // Overwrite the given Z-encoded name with just the fnname. VG_(strcpy)(symbol, func); } VG_(arena_free)(VG_AR_SYMTAB, lib); }
void VG_(setup_code_redirect_table) ( void ) { // Initialise resolved_redirs list. resolved_redirs = VG_(OSet_Create)(offsetof(CodeRedirect, from_addr), NULL, // Use fast comparison symtab_alloc, symtab_free); #if defined(VGP_x86_linux) /* Redirect _dl_sysinfo_int80, which is glibc's default system call routine, to our copy so that the special sysinfo unwind hack in m_stacktrace.c will kick in. */ add_redirect_sym_to_addr( "soname:ld-linux.so.2", "_dl_sysinfo_int80", (Addr)&VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80) ); /* If we're using memcheck, use this intercept right from the start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { add_redirect_sym_to_addr( "soname:ld-linux.so.2", "index", (Addr)&VG_(x86_linux_REDIR_FOR_index) ); } #elif defined(VGP_amd64_linux) /* Redirect vsyscalls to local versions */ add_redirect_addr_to_addr( 0xFFFFFFFFFF600000ULL, (Addr)&VG_(amd64_linux_REDIR_FOR_vgettimeofday) ); add_redirect_addr_to_addr( 0xFFFFFFFFFF600400ULL, (Addr)&VG_(amd64_linux_REDIR_FOR_vtime) ); #elif defined(VGP_ppc32_linux) /* If we're using memcheck, use these intercepts right from the start, otherwise ld.so makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { add_redirect_sym_to_addr( "soname:ld.so.1", "strlen", (Addr)&VG_(ppc32_linux_REDIR_FOR_strlen) ); add_redirect_sym_to_addr( "soname:ld.so.1", "strcmp", (Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp) ); #elif defined(VGP_x86_netbsdelf2) /* Redirect _dl_sysinfo_int80, which is glibc's default system call routine, to our copy so that the special sysinfo unwind hack in m_stacktrace.c will kick in. */ /* add_redirect_sym_to_addr( */ /* "soname:ld-linux.so.2", "_dl_sysinfo_int80", */ /* (Addr)&VG_(x86_netbsd_REDIR_FOR__dl_sysinfo_int80) */ /* ); */ /* If we're using memcheck, use this intercept right from the start, otherwise ld.so (glibc-2.3.5) makes a lot of noise. */ /* if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { */ /* add_redirect_sym_to_addr( */ /* "soname:ld.elf_so", "index", */ /* (Addr)&VG_(x86_linux_REDIR_FOR_index) */ /* ); */ /* } */ // NetBSD: TODO - XXXX /* add_redirect_sym_to_addr( */ /* "soname:ld.elf_so", "_dl_sysinfo_int80", */ /* (Addr)&VG_(x86_linux_REDIR_FOR__dl_sysinfo_int80) */ /* ); */ #else # error Unknown platform #endif } /* Z-decode a symbol into library:func form, eg _vgi_libcZdsoZd6__ZdlPv --> libc.so.6:_ZdlPv Uses the Z-encoding scheme described in pub_core_redir.h. Returns True if demangle OK, False otherwise. */ static Bool Z_decode(const Char* symbol, Char* result, Int nbytes) { # define EMIT(ch) \ do { \ if (j >= nbytes) \ result[j-1] = 0; \ else \ result[j++] = ch; \ } while (0) Bool error = False; Int i, j = 0; Int len = VG_(strlen)(symbol); if (0) VG_(printf)("idm: %s\n", symbol); i = VG_REPLACE_FUNCTION_PREFIX_LEN; /* Chew though the Z-encoded soname part. */ while (True) { if (i >= len) break; if (symbol[i] == '_') /* We found the underscore following the Z-encoded soname. Just copy the rest literally. */ break; if (symbol[i] != 'Z') { EMIT(symbol[i]); i++; continue; } /* We've got a Z-escape. Act accordingly. */ i++; if (i >= len) { /* Hmm, Z right at the end. Something's wrong. */ error = True; EMIT('Z'); break; } switch (symbol[i]) { case 'a': EMIT('*'); break; case 'p': EMIT('+'); break; case 'c': EMIT(':'); break; case 'd': EMIT('.'); break; case 'u': EMIT('_'); break; case 'h': EMIT('-'); break; case 's': EMIT(' '); break; case 'Z': EMIT('Z'); break; default: error = True; EMIT('Z'); EMIT(symbol[i]); break; } i++; } if (error || i >= len || symbol[i] != '_') { /* Something's wrong. Give up. */ VG_(message)(Vg_UserMsg, "intercept: error demangling: %s", symbol); EMIT(0); return False; } /* Copy the rest of the string verbatim. */ i++; EMIT(':'); while (True) { if (i >= len) break; EMIT(symbol[i]); i++; } EMIT(0); if (0) VG_(printf)("%s\n", result); return True; # undef EMIT }