166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/*===-- CommonProfiling.c - Profiling support library support -------------===*\ 266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* 366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* The LLVM Compiler Infrastructure 466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* 566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* This file is distributed under the University of Illinois Open Source 666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* License. See LICENSE.TXT for details. 766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* 866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|*===----------------------------------------------------------------------===*| 966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* 1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* This file implements functions used by the various different types of 1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* profiling implementations. 1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman|* 1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman\*===----------------------------------------------------------------------===*/ 1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "Profiling.h" 1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <assert.h> 1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <sys/types.h> 1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <sys/stat.h> 1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <fcntl.h> 2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <stdio.h> 2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <string.h> 2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#if !defined(_MSC_VER) && !defined(__MINGW32__) 2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <unistd.h> 2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#else 2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <io.h> 2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#endif 2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <stdlib.h> 2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic char *SavedArgs = 0; 3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic unsigned SavedArgsLength = 0; 3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic const char *OutputFilename = "llvmprof.out"; 3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/* save_arguments - Save argc and argv as passed into the program for the file 3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * we output. 3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman */ 3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint save_arguments(int argc, const char **argv) { 3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Length, i; 3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (SavedArgs || !argv) return argc; /* This can be called multiple times */ 4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman /* Check to see if there are any arguments passed into the program for the 4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * profiler. If there are, strip them off and remember their settings. 4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman */ 4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman while (argc > 1 && !strncmp(argv[1], "-llvmprof-", 10)) { 4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman /* Ok, we have an llvmprof argument. Remove it from the arg list and decide 4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * what to do with it. 4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman */ 4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char *Arg = argv[1]; 4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman memmove(&argv[1], &argv[2], (argc-1)*sizeof(char*)); 5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman --argc; 5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!strcmp(Arg, "-llvmprof-output")) { 5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (argc == 1) 5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman puts("-llvmprof-output requires a filename argument!"); 5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else { 5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputFilename = strdup(argv[1]); 5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman memmove(&argv[1], &argv[2], (argc-1)*sizeof(char*)); 5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman --argc; 5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman printf("Unknown option to the profiler runtime: '%s' - ignored.\n", Arg); 6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Length = 0, i = 0; i != (unsigned)argc; ++i) 6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Length += strlen(argv[i])+1; 6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman SavedArgs = (char*)malloc(Length); 6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (Length = 0, i = 0; i != (unsigned)argc; ++i) { 7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Len = strlen(argv[i]); 7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman memcpy(SavedArgs+Length, argv[i], Len); 7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Length += Len; 7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman SavedArgs[Length++] = ' '; 7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman SavedArgsLength = Length; 7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return argc; 7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/* 8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * Retrieves the file descriptor for the profile file. 8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman */ 8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint getOutFile() { 8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman static int OutFile = -1; 8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman /* If this is the first time this function is called, open the output file 8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * for appending, creating it if it does not already exist. 9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman */ 9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OutFile == -1) { 9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutFile = open(OutputFilename, O_CREAT | O_WRONLY, 0666); 9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman lseek(OutFile, 0, SEEK_END); /* O_APPEND prevents seeking */ 9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OutFile == -1) { 9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman fprintf(stderr, "LLVM profiling runtime: while opening '%s': ", 9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputFilename); 9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman perror(""); 9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return(OutFile); 9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman /* Output the command line arguments to the file. */ 10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman { 10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int PTy = ArgumentInfo; 10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int Zeros = 0; 10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (write(OutFile, &PTy, sizeof(int)) < 0 || 10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman write(OutFile, &SavedArgsLength, sizeof(unsigned)) < 0 || 10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman write(OutFile, SavedArgs, SavedArgsLength) < 0 ) { 10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman fprintf(stderr,"error: unable to write to output file."); 10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(0); 11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman /* Pad out to a multiple of four bytes */ 11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (SavedArgsLength & 3) { 11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (write(OutFile, &Zeros, 4-(SavedArgsLength&3)) < 0) { 11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman fprintf(stderr,"error: unable to write to output file."); 11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(0); 11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 11966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 12066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return(OutFile); 12166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 12266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/* write_profiling_data - Write a raw block of profiling counters out to the 12466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * llvmprof.out file. Note that we allow programs to be instrumented with 12566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * multiple different kinds of instrumentation. For this reason, this function 12666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman * may be called more than once. 12766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman */ 12866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid write_profiling_data(enum ProfilingType PT, unsigned *Start, 12966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned NumElements) { 13066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int PTy; 13166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int outFile = getOutFile(); 13266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 13366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman /* Write out this record! */ 13466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PTy = PT; 13566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if( write(outFile, &PTy, sizeof(int)) < 0 || 13666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman write(outFile, &NumElements, sizeof(unsigned)) < 0 || 13766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman write(outFile, Start, NumElements*sizeof(unsigned)) < 0 ) { 13866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman fprintf(stderr,"error: unable to write to output file."); 13966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(0); 14066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 14166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 142