CommonProfiling.c revision 06e950ecb21514b0d09f942c108ad346102278f1
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 6806e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek // Defensively check for a zero length, even though this is unlikely 6906e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek // to happen in practice. This avoids calling malloc() below with a 7006e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek // size of 0. 7106e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek if (Length == 0) { 7206e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek SavedArgs = 0; 7306e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek SavedArgsLength = 0; 7406e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek return argc; 7506e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek } 7606e950ecb21514b0d09f942c108ad346102278f1Ted Kremenek 778b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer SavedArgs = (char*)malloc(Length); 788b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer for (Length = 0, i = 0; i != (unsigned)argc; ++i) { 798b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer unsigned Len = strlen(argv[i]); 808b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer memcpy(SavedArgs+Length, argv[i], Len); 818b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer Length += Len; 828b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer SavedArgs[Length++] = ' '; 838b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer } 848b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer 858b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer SavedArgsLength = Length; 868b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer 878b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer return argc; 888b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer} 898b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer 908b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer 9104317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick/* 9204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * Retrieves the file descriptor for the profile file. 938b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer */ 9404317cc618aeae28910916469e074d8ce0fcaa03Andrew Trickint getOutFile() { 958b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer static int OutFile = -1; 9604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick 9704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick /* If this is the first time this function is called, open the output file 9804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * for appending, creating it if it does not already exist. 998b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer */ 1008b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer if (OutFile == -1) { 10104317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick OutFile = open(OutputFilename, O_CREAT | O_WRONLY, 0666); 10204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick lseek(OutFile, 0, SEEK_END); /* O_APPEND prevents seeking */ 1038b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer if (OutFile == -1) { 1048b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer fprintf(stderr, "LLVM profiling runtime: while opening '%s': ", 1058b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer OutputFilename); 1068b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer perror(""); 10704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick return(OutFile); 1088b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer } 1098b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer 1108b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer /* Output the command line arguments to the file. */ 1118b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer { 1128b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer int PTy = ArgumentInfo; 1138b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer int Zeros = 0; 1146bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova if (write(OutFile, &PTy, sizeof(int)) < 0 || 1156bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova write(OutFile, &SavedArgsLength, sizeof(unsigned)) < 0 || 1166bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova write(OutFile, SavedArgs, SavedArgsLength) < 0 ) { 1176bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova fprintf(stderr,"error: unable to write to output file."); 1186bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova exit(0); 1196bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova } 1208b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer /* Pad out to a multiple of four bytes */ 1216bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova if (SavedArgsLength & 3) { 1226bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova if (write(OutFile, &Zeros, 4-(SavedArgsLength&3)) < 0) { 1236bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova fprintf(stderr,"error: unable to write to output file."); 1246bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova exit(0); 1256bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova } 1266bbba3cab48403f525af5df383462b343fd0d6eeGalina Kistanova } 1278b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer } 1288b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer } 12904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick return(OutFile); 13004317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick} 13104317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick 13204317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick/* write_profiling_data - Write a raw block of profiling counters out to the 13304317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * llvmprof.out file. Note that we allow programs to be instrumented with 13404317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * multiple different kinds of instrumentation. For this reason, this function 13504317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick * may be called more than once. 13604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick */ 13704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trickvoid write_profiling_data(enum ProfilingType PT, unsigned *Start, 13804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick unsigned NumElements) { 13904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick int PTy; 14004317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick int outFile = getOutFile(); 14104317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick 1428b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer /* Write out this record! */ 1438b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer PTy = PT; 14404317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick if( write(outFile, &PTy, sizeof(int)) < 0 || 14504317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick write(outFile, &NumElements, sizeof(unsigned)) < 0 || 14604317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick write(outFile, Start, NumElements*sizeof(unsigned)) < 0 ) { 14704317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick fprintf(stderr,"error: unable to write to output file."); 14804317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick exit(0); 14904317cc618aeae28910916469e074d8ce0fcaa03Andrew Trick } 1508b2e1419cf24a33df5a87c99e367528b44dc28cfReid Spencer} 151