18b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer/*===-- CommonProfiling.c - Profiling support library support -------------===*\
28b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|*
38b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|*                     The LLVM Compiler Infrastructure
48b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|*
504317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick|* This file is distributed under the University of Illinois Open Source
604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick|* License. See LICENSE.TXT for details.
704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick|*
88b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|*===----------------------------------------------------------------------===*|
904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick|*
108b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|* This file implements functions used by the various different types of
118b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|* profiling implementations.
128b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer|*
138b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer\*===----------------------------------------------------------------------===*/
148b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
158b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include "Profiling.h"
1604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick#include <assert.h>
178b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <sys/types.h>
188b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <sys/stat.h>
198b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <fcntl.h>
208b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <stdio.h>
218b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <string.h>
22b89e699b7456b943a0f2a0ba24e1dff8b46bec9fFrancois Pichet#if !defined(_MSC_VER) && !defined(__MINGW32__)
238b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <unistd.h>
24b89e699b7456b943a0f2a0ba24e1dff8b46bec9fFrancois Pichet#else
25b89e699b7456b943a0f2a0ba24e1dff8b46bec9fFrancois Pichet#include <io.h>
26b89e699b7456b943a0f2a0ba24e1dff8b46bec9fFrancois Pichet#endif
278b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer#include <stdlib.h>
288b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
298b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencerstatic char *SavedArgs = 0;
308b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencerstatic unsigned SavedArgsLength = 0;
318b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
328b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencerstatic const char *OutputFilename = "llvmprof.out";
338b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
348b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer/* save_arguments - Save argc and argv as passed into the program for the file
358b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer * we output.
368b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer */
378b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencerint save_arguments(int argc, const char **argv) {
388b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  unsigned Length, i;
398b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  if (SavedArgs || !argv) return argc;  /* This can be called multiple times */
408b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
418b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  /* Check to see if there are any arguments passed into the program for the
428b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer   * profiler.  If there are, strip them off and remember their settings.
438b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer   */
448b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  while (argc > 1 && !strncmp(argv[1], "-llvmprof-", 10)) {
458b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    /* Ok, we have an llvmprof argument.  Remove it from the arg list and decide
468b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer     * what to do with it.
478b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer     */
488b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    const char *Arg = argv[1];
4917da6e7ad8e61e7b80986d1e9a6612943e34971bAaron Ballman    memmove((char**)&argv[1], &argv[2], (argc-1)*sizeof(char*));
508b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    --argc;
518b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
528b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    if (!strcmp(Arg, "-llvmprof-output")) {
538b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      if (argc == 1)
548b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer        puts("-llvmprof-output requires a filename argument!");
558b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      else {
568b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer        OutputFilename = strdup(argv[1]);
5717da6e7ad8e61e7b80986d1e9a6612943e34971bAaron Ballman        memmove((char**)&argv[1], &argv[2], (argc-1)*sizeof(char*));
588b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer        --argc;
598b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      }
608b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    } else {
618b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      printf("Unknown option to the profiler runtime: '%s' - ignored.\n", Arg);
628b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    }
638b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  }
648b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
658b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  for (Length = 0, i = 0; i != (unsigned)argc; ++i)
668b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    Length += strlen(argv[i])+1;
678b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
68ca63acdc5d8b1593e0c1caa56db49a6271618000David Blaikie  /* Defensively check for a zero length, even though this is unlikely
69ca63acdc5d8b1593e0c1caa56db49a6271618000David Blaikie   * to happen in practice.  This avoids calling malloc() below with a
70ca63acdc5d8b1593e0c1caa56db49a6271618000David Blaikie   * size of 0.
71ca63acdc5d8b1593e0c1caa56db49a6271618000David Blaikie   */
7206e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek  if (Length == 0) {
7306e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek    SavedArgs = 0;
7406e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek    SavedArgsLength = 0;
7506e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek    return argc;
7606e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek  }
7706e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek
788b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  SavedArgs = (char*)malloc(Length);
798b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  for (Length = 0, i = 0; i != (unsigned)argc; ++i) {
808b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    unsigned Len = strlen(argv[i]);
818b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    memcpy(SavedArgs+Length, argv[i], Len);
828b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    Length += Len;
838b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    SavedArgs[Length++] = ' ';
848b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  }
858b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
868b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  SavedArgsLength = Length;
878b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
888b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  return argc;
898b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer}
908b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
918b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
9204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick/*
9304317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * Retrieves the file descriptor for the profile file.
948b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer */
9504317cc618aeae28910916469e074d8ce0fcaa03Andrew Trickint getOutFile() {
968b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  static int OutFile = -1;
9704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick
9804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick  /* If this is the first time this function is called, open the output file
9904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick   * for appending, creating it if it does not already exist.
1008b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer   */
1018b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  if (OutFile == -1) {
10204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick    OutFile = open(OutputFilename, O_CREAT | O_WRONLY, 0666);
10304317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick    lseek(OutFile, 0, SEEK_END); /* O_APPEND prevents seeking */
1048b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    if (OutFile == -1) {
1058b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      fprintf(stderr, "LLVM profiling runtime: while opening '%s': ",
1068b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer              OutputFilename);
1078b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      perror("");
10804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick      return(OutFile);
1098b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    }
1108b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer
1118b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    /* Output the command line arguments to the file. */
1128b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    {
1138b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      int PTy = ArgumentInfo;
1148b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      int Zeros = 0;
1156bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova      if (write(OutFile, &PTy, sizeof(int)) < 0 ||
1166bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova          write(OutFile, &SavedArgsLength, sizeof(unsigned)) < 0 ||
1176bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova          write(OutFile, SavedArgs, SavedArgsLength) < 0 ) {
1186bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova        fprintf(stderr,"error: unable to write to output file.");
1196bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova        exit(0);
1206bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova      }
1218b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer      /* Pad out to a multiple of four bytes */
1226bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova      if (SavedArgsLength & 3) {
1236bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova        if (write(OutFile, &Zeros, 4-(SavedArgsLength&3)) < 0) {
1246bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova          fprintf(stderr,"error: unable to write to output file.");
1256bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova          exit(0);
1266bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova        }
1276bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova      }
1288b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer    }
1298b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  }
13004317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick  return(OutFile);
13104317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick}
13204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick
13304317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick/* write_profiling_data - Write a raw block of profiling counters out to the
13404317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * llvmprof.out file.  Note that we allow programs to be instrumented with
13504317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * multiple different kinds of instrumentation.  For this reason, this function
13604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * may be called more than once.
13704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick */
13804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trickvoid write_profiling_data(enum ProfilingType PT, unsigned *Start,
13904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick                          unsigned NumElements) {
14004317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick  int PTy;
14104317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick  int outFile = getOutFile();
14204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick
1438b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  /* Write out this record! */
1448b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer  PTy = PT;
14504317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick  if( write(outFile, &PTy, sizeof(int)) < 0 ||
14604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick      write(outFile, &NumElements, sizeof(unsigned)) < 0 ||
14704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick      write(outFile, Start, NumElements*sizeof(unsigned)) < 0 ) {
14804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick    fprintf(stderr,"error: unable to write to output file.");
14904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick    exit(0);
15004317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick  }
1518b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer}
152