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