char* vt_env_fprefix() { static char* fprefix = NULL; char* tmp; if (! fprefix) { tmp = getenv("VT_FILE_PREFIX"); if (tmp != NULL && strlen(tmp) > 0) { vt_cntl_msg(2, "VT_FILE_PREFIX=%s", tmp); fprefix = replace_vars(tmp); } else { tmp = vt_env_apppath(); if (tmp != NULL && strlen(tmp) > 0) { fprefix = strip_dir(tmp); if (strlen(fprefix) >= 4 && (strcmp(fprefix+(strlen(fprefix)-4), ".out") == 0 || strcmp(fprefix+(strlen(fprefix)-4), ".exe") == 0)) { fprefix[strlen(fprefix)-4] = '\0'; } } else { fprefix = "a"; } } } return fprefix; }
static void get_symtab(void) { char* nm_cmd = NULL; char* nm_filename; FILE* nm_stream; char* line; size_t line_size; uint32_t lineno = 0; uint8_t parse_error = 0; VT_SUSPEND_IO_TRACING(VT_CURRENT_THREAD); /* open nm-file, if given */ nm_filename = vt_env_gnu_nmfile(); if ( nm_filename != NULL && strlen(nm_filename) > 0 ) { vt_cntl_msg(2, "Collecting symbols from file %s", nm_filename); /* open nm-file */ if ( (nm_stream = fopen(nm_filename, "r")) == NULL ) vt_error_msg("Could not open symbol list file %s", nm_filename); } /* otherwise, try to get symbol table automatically */ else { char* apppath; char* nm; size_t nm_cmd_len; vt_cntl_msg(2, "Collecting symbols by 'nm'"); /* get executable path specified by VT_APPPATH */ apppath = vt_env_apppath(); if ( apppath == NULL || strlen(apppath) == 0 ) { vt_error_msg("Could not determine path of executable.\n" "Please set the environment variable VT_APPPATH to the path " "of your executable or set VT_GNU_NMFILE to a symbol list " "file created with 'nm'."); } /* get nm command specified by VT_GNU_NM */ nm = vt_env_gnu_nm(); if ( nm == NULL ) { vt_error_msg("VampirTrace was configured without an 'nm' command.\n" "Please set the environment variable VT_GNU_NM to the 'nm' " "command including command line switches which lists " "symbol/addresses of an object file in BSD-style or set " "VT_GNU_NMFILE to a pre-created symbol list file." ); } /* allocate memory for nm command */ nm_cmd_len = strlen(nm) + 1 + strlen(apppath) + 1; nm_cmd = (char*)malloc(nm_cmd_len * sizeof(char)); if ( nm_cmd == NULL ) vt_error(); /* compose nm command */ snprintf(nm_cmd, nm_cmd_len, "%s %s", nm, apppath); /* execute nm command */ vt_cntl_msg(2, "Executing %s", nm_cmd); nm_stream = popen(nm_cmd, "r"); /* error handling after pclose below */ nm_filename = NULL; } /* allocate memory for lines */ line = (char*)malloc(NM_LINE_BLK_LEN * sizeof(char)); if ( line == NULL ) vt_error(); line_size = NM_LINE_BLK_LEN; /* read lines */ while( nm_stream != NULL && fgets(line, line_size, nm_stream) ) { char* col; char delim[2] = " "; int nc = 1; long addr = -1; char* filename = NULL; char* funcname = NULL; unsigned int lno = VT_NO_LNO; lineno++; /* trigger a parse error, if line is empty */ if ( strlen(line) == 0 ) { parse_error = 1; break; } /* if line seems to be incomplete, enlarge line buffer and read the remaining line */ while( !parse_error && line[strlen(line)-1] != '\n' ) { char tmp[NM_LINE_BLK_LEN]; /* read the remaining line; if it fails (EOF) the line seems to be complete after all */ if ( !fgets(tmp, sizeof(tmp), nm_stream) ) break; /* trigger a parse error, if line is to long (>NM_LINE_MAX_LEN) */ if ( line_size + NM_LINE_BLK_LEN > NM_LINE_MAX_LEN ) { parse_error = 1; break; } /* enlarge line buffer */ line = (char*)realloc(line, (line_size + NM_LINE_BLK_LEN) * sizeof(char)); if ( line == NULL ) vt_error(); line_size += NM_LINE_BLK_LEN; /* complete line */ strcat(line, tmp); } if ( parse_error ) break; /* chop new-line character from line */ if ( line[strlen(line)-1] == '\n' ) line[strlen(line)-1] = '\0'; /* split line to columns */ col = strtok(line, delim); do { if ( nc == 1 ) /* column 1 (address) */ { /* if there is no address in the first column the symbol could be undefined; try get its address later (nc==3) */ if ( strlen(col) == 1 ) { nc++; /* <- will be 3 in the next round */ strcpy(delim, "\t"); } /* otherwise, convert address string */ else { addr = strtol(col, NULL, 16); } } else if ( nc == 2 ) /* column 2 (type) */ { /* type must have a length of 1 */ if ( strlen(col) != 1 ) { parse_error = 1; break; } strcpy(delim, "\t"); } else if ( nc == 3 ) /* column 3 (symbol) */ { funcname = col; strcpy(delim, ":"); /* try to get address of undefined function, if necessary */ if ( addr == -1 ) addr = (long)GET_ADDR_OF_UNDEF_FUNC(funcname); /* ignore function, if its address could not be determined */ if ( addr == 0 ) break; } else if( nc == 4 ) /* column 4 (filename) */ { filename = col; } else /* column 5 (line) */ { lno = atoi(col); if( lno == 0 ) lno = VT_NO_LNO; break; } nc++; col = strtok(0, delim); } while( col ); /* stop reading file, if an parse error occurred */ if ( parse_error ) { break; } /* at least two columns must be read */ else if ( nc < 3 ) { parse_error = 1; break; } /* add symbol to hash table, if we have its address and name */ else if ( addr > 0 && funcname ) { char* n = strdup(funcname); char* p; if ( n == NULL ) vt_error(); /* chop function name at '??', if necessary */ p = strstr(n, "??"); if ( p != NULL && p != n ) *p = '\0'; hash_put(addr, n, filename, lno); } } /* close file/pipe stream */ if ( nm_filename != NULL ) { fclose(nm_stream); if ( parse_error ) { vt_error_msg("%s:%u: could not be parsed.\n" "Please check the content of %s for BSD-style.", nm_filename, lineno, nm_filename); } } else { uint8_t nmcmd_error = (nm_stream == NULL || pclose(nm_stream) != 0); if ( parse_error ) { vt_error_msg("Could not parse 'nm' output created with %s.\n" "Please set the environment variable VT_GNU_NM to the 'nm' " "command including command line switches which lists " "symbol/addresses of an object file in BSD-style or set " "VT_GNU_NMFILE to a pre-created symbol list file.", nm_cmd); } else if ( nmcmd_error ) { vt_error_msg("Failed to execute %s\n" "Please set the environment variable VT_GNU_NM to the 'nm' " "command including command line switches which lists " "symbol/addresses of an object file in BSD-style or set " "VT_GNU_NMFILE to a pre-created symbol list file.", nm_cmd); } free(nm_cmd); } free(line); VT_RESUME_IO_TRACING(VT_CURRENT_THREAD); }
void VT_Dyn_attach() { int mutatee_pid = getpid(); vt_cntl_msg(1, "[%i]: Attaching instrumentor", mutatee_pid); /* Install signal handler for continue execution (SIGUSR1) and abort execution (SIGUSR2) */ if( signal(SIGUSR1, sig_usr1_handler) == SIG_ERR ) vt_error_msg("Could not install handler for signal SIGUSR1"); if( signal(SIGUSR2, sig_usr2_handler) == SIG_ERR ) vt_error_msg("Could not install handler for signal SIGUSR2"); /* The Dyninst attach library (libvt-dynatt) could be set by LD_PRELOAD. Unset this environment variable to avoid recursion. */ putenv((char*)"LD_PRELOAD="); putenv((char*)"DYLD_INSERT_LIBRARIES="); /* equivalent on MacOS */ /* Attach Dyninst instrumentor on running executable */ switch( fork() ) { case -1: { vt_error_msg("Could not attach Dyninst instrumentor"); break; } case 0: { int rc; char cmd[1024]; char* filter = vt_env_filter_spec(); char* shlibs = vt_env_dyn_shlibs(); char* shlibs_arg = NULL; char* mutatee_path = NULL; /* Restore original signal handler */ signal(SIGUSR1, SIG_DFL); signal(SIGUSR2, SIG_DFL); /* Try to get path of mutatee */ vt_pform_init(); mutatee_path = vt_env_apppath(); /* Replace all colons by commas in list of shared libraries */ if ( shlibs && strlen(shlibs) > 0 ) { char* tk; shlibs_arg = (char*)calloc(strlen(shlibs)+2, sizeof(char)); tk = strtok( shlibs, ":" ); do { strcat(shlibs_arg, tk); strcat(shlibs_arg, ","); } while( (tk = strtok( 0, ":" )) ); shlibs_arg[strlen(shlibs_arg)-1] = '\0'; } snprintf(cmd, sizeof(cmd)-1, "%s/vtdyn %s %s %s %s %s %s %s %s %s %s %s " "-p %i %s", vt_installdirs_get(VT_INSTALLDIR_BINDIR), (vt_env_verbose() == 0) ? "-q" : "", (vt_env_verbose() >= 2) ? "-v" : "", filter ? "-f" : "", filter ? filter : "", shlibs_arg ? "-s" : "", shlibs_arg ? shlibs_arg : "", (vt_env_dyn_outer_loops()) ? "--outer-loops" : "", (vt_env_dyn_inner_loops()) ? "--inner-loops" : "", (vt_env_dyn_loop_iters()) ? "--loop-iters" : "", (vt_env_dyn_ignore_nodbg()) ? "--ignore-nodbg" : "", (vt_env_dyn_detach()) ? "" : "--nodetach", mutatee_pid, mutatee_path ? mutatee_path : ""); if ( shlibs_arg ) free(shlibs_arg); /* Start mutator (instrumentor) */ vt_cntl_msg(2, "[%i]: Executing %s", mutatee_pid, cmd); rc = system(cmd); /* Kill mutatee, if an error occurred during attaching */ if(rc != 0) kill(mutatee_pid, SIGUSR2); exit(rc); break; } default: { /* Wait until mutator send signal to continue execution */ vt_cntl_msg(1, "[%i]: Waiting until instrumentation is done", mutatee_pid); do { usleep(1000); } while(mutatee_cont == 0); if ( !mutator_error ) { /* Restore original signal handler */ signal(SIGUSR1, SIG_DFL); signal(SIGUSR2, SIG_DFL); } else { vt_error_msg("An error occurred during instrumenting"); } break; } } }