Пример #1
0
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;
}
Пример #2
0
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);
}
Пример #3
0
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;
    }
  }
}