Message ID | 20120807225534.AA4DF140ADD@rainbowponydeluxe.mtv.corp.google.com |
---|---|
State | New |
Headers | show |
I have committed this to google/main for Chris (approved by Rong). Chris, please prepare a patch to backport this to google/4_7. Teresa On Tue, Aug 7, 2012 at 3:55 PM, Chris Manghane <cmang@google.com> wrote: > Removes references in libgcov.c to functions and structs removed from > pmu-profile.c > > For google/main. Tested with crosstools and bootstrap. > > 2012-08-07 Chris Manghane <cmang@google.com> > > * libgcc/pmu-profile.c > (enum pmu_tool_type): Remove pfmon-specific functions/structs. > (enum pmu_event_type): Ditto. > (enum pmu_state): Ditto. > (enum cpu_vendor_signature): Ditto. > (struct pmu_tool_info): Ditto. > (void gcov_write_branch_mispredict_infos): Ditto. > (get_x86cpu_vendor): Ditto. > (parse_pmu_profile_options): Ditto. > (start_addr2line_symbolizer): Ditto. > (reset_symbolizer_parent_pipes): Ditto. > (reset_symbolizer_child_pipes): Ditto. > (end_addr2line_symbolizer): Ditto. > (symbolize_addr2line): Ditto. > (start_pfmon_module): Ditto. > (convert_pct_to_unsigned): Ditto. > (parse_load_latency_line): Ditto. > (parse_branch_mispredict_line): Ditto. > (parse_pfmon_load_latency): Ditto. > (parse_pfmon_tool_header): Ditto. > (parse_pfmon_branch_mispredicts): Ditto. > (pmu_start): Ditto. > (init_pmu_branch_mispredict): Ditto. > (init_pmu_tool): Ditto. > (__gcov_init_pmu_profiler): Ditto. > (__gcov_start_pmu_profiler): Ditto. > (__gcov_stop_pmu_profiler): Ditto. > (gcov_write_branch_mispredict_line): Ditto. > (gcov_write_load_latency_infos): Ditto. > (gcov_write_branch_mispredict_infos): Ditto. > (gcov_write_tool_header): Ditto. > (__gcov_end_pmu_profiler): Ditto. > * libgcc/libgcov.c > (gcov_alloc_filename): Remove references to pfmon specific > functions/structs. > (pmu_profile_stop): Ditto. > (gcov_exit): Ditto. > (__gcov_init): Ditto. > (__gcov_flush): Ditto. > > Index: libgcc/pmu-profile.c > =================================================================== > --- libgcc/pmu-profile.c (revision 190135) > +++ libgcc/pmu-profile.c (working copy) > @@ -67,169 +67,11 @@ see the files COPYING3 and COPYING.RUNTIME respect > #define XDELETEVEC(p) free(p) > #define XDELETE(p) free(p) > > -#define PFMON_CMD "/usr/bin/pfmon" > -#define ADDR2LINE_CMD "/usr/bin/addr2line" > -#define PMU_TOOL_MAX_ARGS (20) > -static char default_addr2line[] = "??:0"; > -static const char pfmon_ll_header[] = "# counts %self %cum " > - "<10 <32 <64 <256 <1024 >=1024 %wself " > - "code addr symbol\n"; > -static const char pfmon_bm_header[] = > - "# counts %self %cum code addr symbol\n"; > - > -const char *pfmon_intel_ll_args[PMU_TOOL_MAX_ARGS] = { > - PFMON_CMD, > - "--aggregate-results", > - "--follow-all", > - "--with-header", > - "--smpl-module=pebs-ll", > - "--ld-lat-threshold=4", > - "--pebs-ll-dcmiss-code", > - "--resolve-addresses", > - "-emem_inst_retired:LATENCY_ABOVE_THRESHOLD", > - "--long-smpl-periods=10000", > - 0 /* terminating NULL must be present */ > -}; > - > -const char *pfmon_amd_ll_args[PMU_TOOL_MAX_ARGS] = { > - PFMON_CMD, > - "--aggregate-results", > - "--follow-all", > - "-uk", > - "--with-header", > - "--smpl-module=ibs", > - "--resolve-addresses", > - "-eibsop_event:uops", > - "--ibs-dcmiss-code", > - "--long-smpl-periods=0xffff0", > - 0 /* terminating NULL must be present */ > -}; > - > -const char *pfmon_intel_brm_args[PMU_TOOL_MAX_ARGS] = { > - PFMON_CMD, > - "--aggregate-results", > - "--follow-all", > - "--with-header", > - "--resolve-addresses", > - "-eMISPREDICTED_BRANCH_RETIRED", > - "--long-smpl-periods=10000", > - 0 /* terminating NULL must be present */ > -}; > - > -const char *pfmon_amd_brm_args[PMU_TOOL_MAX_ARGS] = { > - PFMON_CMD, > - "--aggregate-results", > - "--follow-all", > - "--with-header", > - "--resolve-addresses", > - "-eRETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS", > - "--long-smpl-periods=10000", > - 0 /* terminating NULL must be present */ > -}; > - > -const char *addr2line_args[PMU_TOOL_MAX_ARGS] = { > - ADDR2LINE_CMD, > - "-e", > - 0 /* terminating NULL must be present */ > -}; > - > - > -enum pmu_tool_type > -{ > - PTT_PFMON, > - PTT_LAST > -}; > - > -enum pmu_event_type > -{ > - PET_INTEL_LOAD_LATENCY, > - PET_AMD_LOAD_LATENCY, > - PET_INTEL_BRANCH_MISPREDICT, > - PET_AMD_BRANCH_MISPREDICT, > - PET_LAST > -}; > - > -typedef struct pmu_tool_fns { > - const char *name; /* name of the pmu tool */ > - /* pmu tool commandline argument. */ > - const char **arg_array; > - /* Initialize pmu module. */ > - void *(*init_pmu_module) (void); > - /* Start profililing. */ > - void (*start_pmu_module) (pid_t ppid, char *tmpfile, const char **args); > - /* Stop profililing. */ > - void (*stop_pmu_module) (void); > - /* How to parse the output generated by the PMU tool. */ > - int (*parse_pmu_output) (char *filename, void *pmu_data); > - /* How to write parsed pmu data into gcda file. */ > - void (*gcov_write_pmu_data) (void *data); > - /* How to cleanup any data structure created during parsing. */ > - void (*cleanup_pmu_data) (void *data); > - /* How to initialize symbolizer for the PPID. */ > - int (*start_symbolizer) (pid_t ppid); > - void (*end_symbolizer) (void); > - char *(*symbolize) (void *addr); > -} pmu_tool_fns; > - > -enum pmu_state > -{ > - PMU_NONE, /* Not configurated at all. */ > - PMU_INITIALIZED, /* Configured and initialized. */ > - PMU_ERROR, /* Configuration error. Cannot recover. */ > - PMU_ON, /* Currently profiling. */ > - PMU_OFF /* Currently stopped, but can be restarted. */ > -}; > - > -enum cpu_vendor_signature > -{ > - CPU_VENDOR_UKNOWN = 0, > - CPU_VENDOR_INTEL = 0x756e6547, /* Genu */ > - CPU_VENDOR_AMD = 0x68747541 /* Auth */ > -}; > - > -/* Info about pmu tool during the run time. */ > -struct pmu_tool_info > -{ > - /* Current pmu tool. */ > - enum pmu_tool_type tool; > - /* Current event. */ > - enum pmu_event_type event; > - /* filename for storing the pmu profile. */ > - char *pmu_profile_filename; > - /* Intermediate file where the tool stores the PMU data. */ > - char *raw_pmu_profile_filename; > - /* Where PMU tool's stderr should be stored. */ > - char *tool_stderr_filename; > - enum pmu_state pmu_profiling_state; > - enum cpu_vendor_signature cpu_vendor; /* as discovered by cpuid */ > - pid_t pmu_tool_pid; /* process id of the pmu tool */ > - pid_t symbolizer_pid; /* process id of the symbolizer */ > - int symbolizer_to_pipefd[2]; /* pipe for writing to the symbolizer */ > - int symbolizer_from_pipefd[2]; /* pipe for reading from the symbolizer */ > - void *pmu_data; /* an opaque pointer for the tool to store pmu data */ > - int verbose; /* turn on additional debugging */ > - unsigned top_n_address; /* how many addresses to symbolize */ > - pmu_tool_fns *tool_details; /* list of functions how to start/stop/parse */ > -}; > - > -/* Global struct for recordkeeping. */ > -static struct pmu_tool_info *the_pmu_tool_info; > - > -/* Additional info is printed if these are non-zero. */ > -static int tool_debug = 0; > -static int sym_debug = 0; > - > -static int parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info); > -static int parse_branch_mispredict_line (char *line, > - gcov_pmu_brm_info_t *brm_info); > static unsigned convert_pct_to_unsigned (float pct); > -static void start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args); > static void *init_pmu_load_latency (void); > static void *init_pmu_branch_mispredict (void); > static void destroy_load_latency_infos (void *info); > static void destroy_branch_mispredict_infos (void *info); > -static int parse_pfmon_load_latency (char *filename, void *pmu_data); > -static int parse_pfmon_branch_mispredicts (char *filename, void *pmu_data); > static gcov_unsigned_t gcov_tag_pmu_tool_header_length (gcov_pmu_tool_header_t > *header); > static void gcov_write_tool_header (gcov_pmu_tool_header_t *header); > @@ -238,456 +80,7 @@ static void gcov_write_branch_mispredict_infos (vo > static void gcov_write_ll_line (const gcov_pmu_ll_info_t *ll_info); > static void gcov_write_branch_mispredict_line (const gcov_pmu_brm_info_t > *brm_info); > -static int start_addr2line_symbolizer (pid_t pid); > -static void end_addr2line_symbolizer (void); > -static char *symbolize_addr2line (void *p); > -static void reset_symbolizer_parent_pipes (void); > -static void reset_symbolizer_child_pipes (void); > -/* parse and cache relevant tool info. */ > -static int parse_pmu_profile_options (const char *options); > -static gcov_pmu_tool_header_t *parse_pfmon_tool_header (FILE *fp, > - const char *end_header); > > - > -/* How to access the necessary functions for the PMU tools. */ > -pmu_tool_fns all_pmu_tool_fns[PTT_LAST][PET_LAST] = { > - { > - { > - "intel-load-latency", /* name */ > - pfmon_intel_ll_args, /* tool args */ > - init_pmu_load_latency, /* initialization */ > - start_pfmon_module, /* start */ > - 0, /* stop */ > - parse_pfmon_load_latency, /* parse */ > - gcov_write_load_latency_infos, /* write */ > - destroy_load_latency_infos, /* cleanup */ > - start_addr2line_symbolizer, /* start symbolizer */ > - end_addr2line_symbolizer, /* end symbolizer */ > - symbolize_addr2line, /* symbolize */ > - }, > - { > - "amd-load-latency", /* name */ > - pfmon_amd_ll_args, /* tool args */ > - init_pmu_load_latency, /* initialization */ > - start_pfmon_module, /* start */ > - 0, /* stop */ > - parse_pfmon_load_latency, /* parse */ > - gcov_write_load_latency_infos, /* write */ > - destroy_load_latency_infos, /* cleanup */ > - start_addr2line_symbolizer, /* start symbolizer */ > - end_addr2line_symbolizer, /* end symbolizer */ > - symbolize_addr2line, /* symbolize */ > - }, > - { > - "intel-branch-mispredict", /* name */ > - pfmon_intel_brm_args, /* tool args */ > - init_pmu_branch_mispredict, /* initialization */ > - start_pfmon_module, /* start */ > - 0, /* stop */ > - parse_pfmon_branch_mispredicts, /* parse */ > - gcov_write_branch_mispredict_infos,/* write */ > - destroy_branch_mispredict_infos, /* cleanup */ > - start_addr2line_symbolizer, /* start symbolizer */ > - end_addr2line_symbolizer, /* end symbolizer */ > - symbolize_addr2line, /* symbolize */ > - }, > - { > - "amd-branch-mispredict", /* name */ > - pfmon_amd_brm_args, /* tool args */ > - init_pmu_branch_mispredict, /* initialization */ > - start_pfmon_module, /* start */ > - 0, /* stop */ > - parse_pfmon_branch_mispredicts, /* parse */ > - gcov_write_branch_mispredict_infos,/* write */ > - destroy_branch_mispredict_infos, /* cleanup */ > - start_addr2line_symbolizer, /* start symbolizer */ > - end_addr2line_symbolizer, /* end symbolizer */ > - symbolize_addr2line, /* symbolize */ > - } > - } > -}; > - > -/* Determine the CPU vendor. Currently only distinguishes x86 based > - cpus where the vendor is either Intel or AMD. Returns one of the > - enum cpu_vendor_signatures. */ > - > -static unsigned int > -get_x86cpu_vendor (void) > -{ > - unsigned int vendor = CPU_VENDOR_UKNOWN; > - > -#if (defined (__x86_64__) || defined (__i386__)) > - if (__get_cpuid_max (0, &vendor) < 1) > - return CPU_VENDOR_UKNOWN; /* Cannot determine cpu type. */ > -#endif > - > - if (vendor == CPU_VENDOR_INTEL || vendor == CPU_VENDOR_AMD) > - return vendor; > - else > - return CPU_VENDOR_UKNOWN; > -} > - > - > -/* Parse PMU tool option string provided on the command line and store > - information in global structure. Return 0 on success, otherwise > - return 1. Any changes to this should be synced with > - check_pmu_profile_options() which does compile time check. */ > - > -static int > -parse_pmu_profile_options (const char *options) > -{ > - enum pmu_tool_type ptt = the_pmu_tool_info->tool; > - enum pmu_event_type pet = PET_LAST; > - const char *pmutool_path; > - the_pmu_tool_info->cpu_vendor = get_x86cpu_vendor (); > - /* Determine the platform we are running on. */ > - if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_UKNOWN) > - { > - /* Cpuid failed or uknown vendor. */ > - the_pmu_tool_info->pmu_profiling_state = PMU_ERROR; > - return 1; > - } > - > - /* Validate the options. */ > - if (strcmp(options, "load-latency") && > - strcmp(options, "load-latency-verbose") && > - strcmp(options, "branch-mispredict") && > - strcmp(options, "branch-mispredict-verbose")) > - return 1; > - > - /* Check if are aksed to collect load latency PMU data. */ > - if (!strcmp(options, "load-latency") || > - !strcmp(options, "load-latency-verbose")) > - { > - if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL) > - pet = PET_INTEL_LOAD_LATENCY; > - else > - pet = PET_AMD_LOAD_LATENCY; > - if (!strcmp(options, "load-latency-verbose")) > - the_pmu_tool_info->verbose = 1; > - } > - > - /* Check if are aksed to collect branch mispredict PMU data. */ > - if (!strcmp(options, "branch-mispredict") || > - !strcmp(options, "branch-mispredict-verbose")) > - { > - if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL) > - pet = PET_INTEL_BRANCH_MISPREDICT; > - else > - pet = PET_AMD_BRANCH_MISPREDICT; > - if (!strcmp(options, "branch-mispredict-verbose")) > - the_pmu_tool_info->verbose = 1; > - } > - > - the_pmu_tool_info->tool_details = &all_pmu_tool_fns[ptt][pet]; > - the_pmu_tool_info->event = pet; > - > - /* Allow users to override the default tool path. */ > - pmutool_path = getenv ("GCOV_PMUTOOL_PATH"); > - if (pmutool_path && strlen (pmutool_path)) > - the_pmu_tool_info->tool_details->arg_array[0] = pmutool_path; > - > - return 0; > -} > - > -/* Do the initialization of addr2line symbolizer for the process id > - given by TASK_PID. It forks an addr2line process and creates two > - pipes where addresses can be written and source_filename:line_num > - entries can be read. Returns 0 on success, non-zero otherwise. */ > - > -static int > -start_addr2line_symbolizer (pid_t task_pid) > -{ > - pid_t pid; > - char *addr2line_path; > - > - /* Allow users to override the default addr2line path. */ > - addr2line_path = getenv ("GCOV_ADDR2LINE_PATH"); > - if (addr2line_path && strlen (addr2line_path)) > - addr2line_args[0] = addr2line_path; > - > - if (pipe (the_pmu_tool_info->symbolizer_from_pipefd) == -1) > - { > - fprintf (stderr, "Cannot create symbolizer write pipe.\n"); > - return 1; > - } > - if (pipe (the_pmu_tool_info->symbolizer_to_pipefd) == -1) > - { > - fprintf (stderr, "Cannot create symbolizer read pipe.\n"); > - return 1; > - } > - > - pid = fork (); > - if (pid == -1) > - { > - /* error condition */ > - fprintf (stderr, "Cannot create symbolizer process.\n"); > - reset_symbolizer_parent_pipes (); > - reset_symbolizer_child_pipes (); > - return 1; > - } > - > - if (pid == 0) > - { > - /* child does an exec and then connects to/from the pipe */ > - unsigned n_args = 0; > - char proc_exe_buf[128]; > - int new_write_fd, new_read_fd; > - int i; > - > - /* Go over the current addr2line args. */ > - for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i) > - n_args++; > - > - /* We are going to add one more arg for the /proc/pid/exe */ > - if (n_args >= (PMU_TOOL_MAX_ARGS - 1)) > - { > - fprintf (stderr, "too many addr2line args: %d\n", n_args); > - _exit (0); > - } > - snprintf (proc_exe_buf, sizeof (proc_exe_buf), "/proc/%d/exe", > - task_pid); > - > - /* Add the extra arg for the process id. */ > - addr2line_args[n_args] = proc_exe_buf; > - n_args++; > - > - addr2line_args[n_args] = (const char *)NULL; /* terminating NULL */ > - > - if (sym_debug) > - { > - fprintf (stderr, "addr2line args:"); > - for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i) > - fprintf (stderr, " %s", addr2line_args[i]); > - fprintf (stderr, "\n"); > - } > - > - /* Close unused ends of the two pipes. */ > - reset_symbolizer_child_pipes (); > - > - /* Connect the pipes to stdin/stdout of the child process. */ > - new_read_fd = dup2 (the_pmu_tool_info->symbolizer_to_pipefd[0], 0); > - new_write_fd = dup2 (the_pmu_tool_info->symbolizer_from_pipefd[1], 1); > - if (new_read_fd == -1 || new_write_fd == -1) > - { > - fprintf (stderr, "could not dup symbolizer fds\n"); > - reset_symbolizer_parent_pipes (); > - reset_symbolizer_child_pipes (); > - _exit (0); > - } > - the_pmu_tool_info->symbolizer_to_pipefd[0] = new_read_fd; > - the_pmu_tool_info->symbolizer_from_pipefd[1] = new_write_fd; > - > - /* Do execve with NULL env. */ > - execve (addr2line_args[0], (char * const*)addr2line_args, > - (char * const*)NULL); > - /* exec returned, an error condition. */ > - fprintf (stderr, "could not create symbolizer process: %s\n", > - addr2line_args[0]); > - reset_symbolizer_parent_pipes (); > - reset_symbolizer_child_pipes (); > - _exit (0); > - } > - else > - { > - /* parent */ > - the_pmu_tool_info->symbolizer_pid = pid; > - /* Close unused ends of the two pipes. */ > - reset_symbolizer_parent_pipes (); > - return 0; > - } > - return 0; > -} > - > -/* Close unused write end of the from-pipe and read end of the > - to-pipe. */ > - > -static void > -reset_symbolizer_parent_pipes (void) > -{ > - if (the_pmu_tool_info->symbolizer_from_pipefd[1] != -1) > - { > - close (the_pmu_tool_info->symbolizer_from_pipefd[1]); > - the_pmu_tool_info->symbolizer_from_pipefd[1] = -1; > - } > - if (the_pmu_tool_info->symbolizer_to_pipefd[0] != -1) > - { > - close (the_pmu_tool_info->symbolizer_to_pipefd[0]); > - the_pmu_tool_info->symbolizer_to_pipefd[0] = -1; > - } > -} > - > -/* Close unused write end of the to-pipe and read end of the > - from-pipe. */ > - > -static void > -reset_symbolizer_child_pipes (void) > -{ > - if (the_pmu_tool_info->symbolizer_to_pipefd[1] != -1) > - { > - close (the_pmu_tool_info->symbolizer_to_pipefd[1]); > - the_pmu_tool_info->symbolizer_to_pipefd[1] = -1; > - } > - if (the_pmu_tool_info->symbolizer_from_pipefd[0] != -1) > - { > - close (the_pmu_tool_info->symbolizer_from_pipefd[0]); > - the_pmu_tool_info->symbolizer_from_pipefd[0] = -1; > - } > -} > - > - > -/* Perform cleanup for the symbolizer process. */ > - > -static void > -end_addr2line_symbolizer (void) > -{ > - int pid_status; > - int wait_status; > - pid_t pid = the_pmu_tool_info->symbolizer_pid; > - > - /* Symbolizer was not running. */ > - if (!pid) > - return; > - > - reset_symbolizer_parent_pipes (); > - reset_symbolizer_child_pipes (); > - kill (pid, SIGTERM); > - wait_status = waitpid (pid, &pid_status, 0); > - if (sym_debug) > - { > - if (wait_status == pid) > - fprintf (stderr, "Normal exit. symbolizer terminated.\n"); > - else > - fprintf (stderr, "Abnormal exit. symbolizer status, %d.\n", pid_status); > - } > - the_pmu_tool_info->symbolizer_pid = 0; /* Symoblizer no longer running. */ > -} > - > - > -/* Given an address ADDR, return a string containing > - source_filename:line_num entries. */ > - > -static char * > -symbolize_addr2line (void *addr) > -{ > - char buf[32]; /* holds the ascii version of address */ > - int write_count; > - int read_count; > - char *srcfile_linenum; > - size_t max_length = 1024; > - > - if (!the_pmu_tool_info->symbolizer_pid) > - return default_addr2line; /* symbolizer is not running */ > - > - write_count = snprintf (buf, sizeof (buf), "%p\n", addr); > - > - /* Write the address into the pipe. */ > - if (write (the_pmu_tool_info->symbolizer_to_pipefd[1], buf, write_count) > - < write_count) > - { > - if (sym_debug) > - fprintf (stderr, "Cannot write symbolizer pipe.\n"); > - return default_addr2line; > - } > - > - srcfile_linenum = XNEWVEC (char, max_length); > - read_count = read (the_pmu_tool_info->symbolizer_from_pipefd[0], > - srcfile_linenum, max_length); > - if (read_count == -1) > - { > - if (sym_debug) > - fprintf (stderr, "Cannot read symbolizer pipe.\n"); > - XDELETEVEC (srcfile_linenum); > - return default_addr2line; > - } > - > - srcfile_linenum[read_count] = 0; > - if (sym_debug) > - fprintf (stderr, "symbolizer: for address %p, read_count %d, got %s\n", > - addr, read_count, srcfile_linenum); > - return srcfile_linenum; > -} > - > -/* Start monitoring PPID process via pfmon tool using TMPFILE as a > - file to store the raw data and using PFMON_ARGS as the command line > - arguments. */ > - > -static void > -start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args) > -{ > - int i; > - unsigned int n_args = 0; > - unsigned n_chars; > - char pid_buf[64]; > - char filename_buf[1024]; > - char top_n_buf[24]; > - unsigned extra_args; > - > - /* Go over the current pfmon args */ > - for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i) > - n_args++; > - > - if (the_pmu_tool_info->verbose) > - extra_args = 4; /* account for additional --verbose */ > - else > - extra_args = 3; > - > - /* We are going to add args. */ > - if (n_args >= (PMU_TOOL_MAX_ARGS - extra_args)) > - { > - fprintf (stderr, "too many pfmon args: %d\n", n_args); > - _exit (0); > - } > - > - n_chars = snprintf (pid_buf, sizeof (pid_buf), "--attach-task=%ld", > - (long)ppid); > - if (n_chars >= sizeof (pid_buf)) > - { > - fprintf (stderr, "pfmon task id too long: %s\n", pid_buf); > - return; > - } > - pfmon_args[n_args] = pid_buf; > - n_args++; > - > - n_chars = snprintf (filename_buf, sizeof (filename_buf), "--smpl-outfile=%s", > - tmpfile); > - if (n_chars >= sizeof (filename_buf)) > - { > - fprintf (stderr, "pfmon filename too long: %s\n", filename_buf); > - return; > - } > - pfmon_args[n_args] = filename_buf; > - n_args++; > - > - n_chars = snprintf (top_n_buf, sizeof (top_n_buf), "--smpl-show-top=%d", > - the_pmu_tool_info->top_n_address); > - if (n_chars >= sizeof (top_n_buf)) > - { > - fprintf (stderr, "pfmon option too long: %s\n", top_n_buf); > - return; > - } > - pfmon_args[n_args] = top_n_buf; > - n_args++; > - > - if (the_pmu_tool_info->verbose) { > - /* Add --verbose as well. */ > - pfmon_args[n_args] = "--verbose"; > - n_args++; > - } > - pfmon_args[n_args] = (char *)NULL; > - > - if (tool_debug) > - { > - fprintf (stderr, "pfmon args:"); > - for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i) > - fprintf (stderr, " %s", pfmon_args[i]); > - fprintf (stderr, "\n"); > - } > - /* Do execve with NULL env. */ > - execve (pfmon_args[0], (char *const *)pfmon_args, (char * const*)NULL); > - /* does not return */ > -} > - > /* Convert a fractional PCT to an unsigned integer after > muliplying by 100. */ > > @@ -697,147 +90,6 @@ convert_pct_to_unsigned (float pct) > return (unsigned)(pct * 100.0f); > } > > -/* Parse the load latency info pointed by LINE and save it into > - LL_INFO. Returns 0 if the line was parsed successfully, non-zero > - otherwise. > - > - An example header+line look like these: > - "counts %self %cum <10 <32 <64 <256 <1024 >=1024 > - %wself code addr symbol" > - "218 24.06% 24.06% 100.00% 0.00% 0.00% 0.00% 0.00% 0.00% 22.70% > - 0x0000000000413e75 CalcSSIM(...)+965</tmp/psnr>" > -*/ > - > -static int > -parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info) > -{ > - unsigned counts; > - /* These are percentages parsed as floats, but then converted to > - integers after multiplying by 100. */ > - float self, cum, lt_10, lt_32, lt_64, lt_256, lt_1024, gt_1024, wself; > - long unsigned int p; > - int n_values; > - pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details; > - > - n_values = sscanf (line, "%u%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%lx", > - &counts, &self, &cum, <_10, <_32, <_64, <_256, > - <_1024, >_1024, &wself, &p); > - if (n_values != 11) > - return 1; > - > - /* Values read successfully. Do the assignment after converting > - * percentages into ints. */ > - ll_info->counts = counts; > - ll_info->self = convert_pct_to_unsigned (self); > - ll_info->cum = convert_pct_to_unsigned (cum); > - ll_info->lt_10 = convert_pct_to_unsigned (lt_10); > - ll_info->lt_32 = convert_pct_to_unsigned (lt_32); > - ll_info->lt_64 = convert_pct_to_unsigned (lt_64); > - ll_info->lt_256 = convert_pct_to_unsigned (lt_256); > - ll_info->lt_1024 = convert_pct_to_unsigned (lt_1024); > - ll_info->gt_1024 = convert_pct_to_unsigned (gt_1024); > - ll_info->wself = convert_pct_to_unsigned (wself); > - ll_info->code_addr = p; > - > - /* Run the raw address through the symbolizer. */ > - if (tool_details->symbolize) > - { > - char *sym_info = tool_details->symbolize ((void *)p); > - /* sym_info is of the form src_filename:linenum. Descriminator is > - currently not supported by addr2line. */ > - char *sep = strchr (sym_info, ':'); > - if (!sep) > - { > - /* Assume entire string is srcfile. */ > - ll_info->filename = (char *)sym_info; > - ll_info->line = 0; > - } > - else > - { > - /* Terminate the filename string at the separator. */ > - *sep = 0; > - ll_info->filename = (char *)sym_info; > - /* Convert rest of the sym info to a line number. */ > - ll_info->line = atol (sep+1); > - } > - ll_info->discriminator = 0; > - } > - else > - { > - /* No symbolizer available. */ > - ll_info->filename = NULL; > - ll_info->line = 0; > - ll_info->discriminator = 0; > - } > - return 0; > -} > - > -/* Parse the branch mispredict info pointed by LINE and save it into > - BRM_INFO. Returns 0 if the line was parsed successfully, non-zero > - otherwise. > - > - An example header+line look like these: > - "counts %self %cum code addr symbol" > - "6869 37.67% 37.67% 0x00000000004007e5 sum(std::vector<int*, > - std::allocator<int*> > const&)+51</root/tmp/array>" > -*/ > - > -static int > -parse_branch_mispredict_line (char *line, gcov_pmu_brm_info_t *brm_info) > -{ > - unsigned counts; > - /* These are percentages parsed as floats, but then converted to > - ints after multiplying by 100. */ > - float self, cum; > - long unsigned int p; > - int n_values; > - pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details; > - > - n_values = sscanf (line, "%u%f%%%f%%%lx", > - &counts, &self, &cum, &p); > - if (n_values != 4) > - return 1; > - > - /* Values read successfully. Do the assignment after converting > - * percentages into ints. */ > - brm_info->counts = counts; > - brm_info->self = convert_pct_to_unsigned (self); > - brm_info->cum = convert_pct_to_unsigned (cum); > - brm_info->code_addr = p; > - > - /* Run the raw address through the symbolizer. */ > - if (tool_details->symbolize) > - { > - char *sym_info = tool_details->symbolize ((void *)p); > - /* sym_info is of the form src_filename:linenum. Descriminator is > - currently not supported by addr2line. */ > - char *sep = strchr (sym_info, ':'); > - if (!sep) > - { > - /* Assume entire string is srcfile. */ > - brm_info->filename = sym_info; > - brm_info->line = 0; > - } > - else > - { > - /* Terminate the filename string at the separator. */ > - *sep = 0; > - brm_info->filename = sym_info; > - /* Convert rest of the sym info to a line number. */ > - brm_info->line = atol (sep+1); > - } > - brm_info->discriminator = 0; > - } > - else > - { > - /* No symbolizer available. */ > - brm_info->filename = NULL; > - brm_info->line = 0; > - brm_info->discriminator = 0; > - } > - return 0; > -} > - > /* Delete load latency info structures INFO. */ > > static void > @@ -876,309 +128,6 @@ destroy_branch_mispredict_infos (void *info) > brm_infos->brm_count = 0; > } > > -/* Parse FILENAME for load latency lines into a structure > - PMU_DATA. Returns 0 on on success. Returns non-zero on > - failure. */ > - > -static int > -parse_pfmon_load_latency (char *filename, void *pmu_data) > -{ > - FILE *fp; > - size_t buflen = 2*1024; > - char *buf; > - ll_infos_t *load_latency_infos = (ll_infos_t *)pmu_data; > - gcov_pmu_tool_header_t *tool_header = 0; > - > - if ((fp = fopen (filename, "r")) == NULL) > - { > - fprintf (stderr, "cannot open pmu data file: %s\n", filename); > - return 1; > - } > - > - if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_ll_header))) > - { > - fprintf (stderr, "cannot parse pmu data file header: %s\n", filename); > - return 1; > - } > - > - buf = XNEWVEC (char, buflen); > - while (fgets (buf, buflen, fp)) > - { > - gcov_pmu_ll_info_t *ll_info = XNEW (gcov_pmu_ll_info_t); > - if (!parse_load_latency_line (buf, ll_info)) > - { > - /* valid line, add to the array */ > - load_latency_infos->ll_count++; > - if (load_latency_infos->ll_count >= > - load_latency_infos->alloc_ll_count) > - { > - /* need to realloc */ > - load_latency_infos->ll_array = > - realloc (load_latency_infos->ll_array, > - 2 * load_latency_infos->alloc_ll_count); > - if (load_latency_infos->ll_array == NULL) > - { > - fprintf (stderr, "Cannot allocate load latency memory.\n"); > - __destroy_pmu_tool_header (tool_header); > - free (buf); > - fclose (fp); > - return 1; > - } > - } > - load_latency_infos->ll_array[load_latency_infos->ll_count - 1] = > - ll_info; > - } > - else > - /* Delete invalid line. */ > - XDELETE (ll_info); > - } > - free (buf); > - fclose (fp); > - load_latency_infos->pmu_tool_header = tool_header; > - return 0; > -} > - > -/* Parse open file FP until END_HEADER is seen. The data matching > - gcov_pmu_tool_header_t fields is saved and returned in a new > - struct. In case of failure, it returns NULL. */ > - > -static gcov_pmu_tool_header_t * > -parse_pfmon_tool_header (FILE *fp, const char *end_header) > -{ > - static const char tag_hostname[] = "# hostname: "; > - static const char tag_kversion[] = "# kernel version: "; > - static const char tag_hostcpu[] = "# host CPUs: "; > - static const char tag_column_desc_start[] = "# description of columns:"; > - static const char tag_column_desc_end[] = > - "# other columns are self-explanatory"; > - size_t buflen = 4*1024; > - char *buf, *buf_start, *buf_end; > - gcov_pmu_tool_header_t *tool_header = XNEWVEC (gcov_pmu_tool_header_t, 1); > - char *hostname = 0; > - char *kversion = 0; > - char *hostcpu = 0; > - char *column_description = 0; > - char *column_desc_start = 0; > - char *column_desc_end = 0; > - const char *column_header = 0; > - int got_hostname = 0; > - int got_kversion = 0 ; > - int got_hostcpu = 0; > - int got_end_header = 0; > - int got_column_description = 0; > - > - buf = XNEWVEC (char, buflen); > - buf_start = buf; > - buf_end = buf + buflen; > - while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp)) > - { > - if (strncmp (end_header, buf, buf_end - buf) == 0) > - { > - got_end_header = 1; > - break; > - } > - if (!got_hostname && > - strncmp (buf, tag_hostname, strlen (tag_hostname)) == 0) > - { > - size_t len = strlen (buf) - strlen (tag_hostname); > - hostname = XNEWVEC (char, len); > - memcpy (hostname, buf + strlen (tag_hostname), len); > - hostname[len - 1] = 0; > - tool_header->hostname = hostname; > - got_hostname = 1; > - } > - > - if (!got_kversion && > - strncmp (buf, tag_kversion, strlen (tag_kversion)) == 0) > - { > - size_t len = strlen (buf) - strlen (tag_kversion); > - kversion = XNEWVEC (char, len); > - memcpy (kversion, buf + strlen (tag_kversion), len); > - kversion[len - 1] = 0; > - tool_header->kernel_version = kversion; > - got_kversion = 1; > - } > - > - if (!got_hostcpu && > - strncmp (buf, tag_hostcpu, strlen (tag_hostcpu)) == 0) > - { > - size_t len = strlen (buf) - strlen (tag_hostcpu); > - hostcpu = XNEWVEC (char, len); > - memcpy (hostcpu, buf + strlen (tag_hostcpu), len); > - hostcpu[len - 1] = 0; > - tool_header->host_cpu = hostcpu; > - got_hostcpu = 1; > - } > - if (!got_column_description && > - strncmp (buf, tag_column_desc_start, strlen (tag_column_desc_start)) > - == 0) > - { > - column_desc_start = buf; > - column_desc_end = 0; > - /* Continue reading until end of the column descriptor. */ > - while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp)) > - { > - if (strncmp (buf, tag_column_desc_end, > - strlen (tag_column_desc_end)) == 0) > - { > - column_desc_end = buf + strlen (tag_column_desc_end); > - break; > - } > - buf += strlen (buf); > - } > - if (column_desc_end) > - { > - /* Found the end, copy it into a new string. */ > - column_description = XNEWVEC (char, column_desc_end - > - column_desc_start + 1); > - got_column_description = 1; > - strcpy (column_description, column_desc_start); > - tool_header->column_description = column_description; > - } > - } > - buf += strlen (buf); > - } > - > - /* If we are missing any of the fields, return NULL. */ > - if (!got_end_header || !got_hostname || !got_kversion || !got_hostcpu > - || !got_column_description) > - { > - free (hostname); > - free (kversion); > - free (hostcpu); > - free (column_description); > - free (buf_start); > - free (tool_header); > - return NULL; > - } > - > - switch (the_pmu_tool_info->event) > - { > - case PET_INTEL_LOAD_LATENCY: > - case PET_AMD_LOAD_LATENCY: > - column_header = pfmon_ll_header; > - break; > - case PET_INTEL_BRANCH_MISPREDICT: > - case PET_AMD_BRANCH_MISPREDICT: > - column_header = pfmon_bm_header; > - break; > - default: > - break; > - } > - tool_header->column_header = strdup (column_header); > - tool_header->full_header = buf_start; > - return tool_header; > -} > - > - > -/* Parse FILENAME for branch mispredict lines into a structure > - PMU_DATA. Returns 0 on on success. Returns non-zero on > - failure. */ > - > -static int > -parse_pfmon_branch_mispredicts (char *filename, void *pmu_data) > -{ > - FILE *fp; > - size_t buflen = 2*1024; > - char *buf; > - brm_infos_t *brm_infos = (brm_infos_t *)pmu_data; > - gcov_pmu_tool_header_t *tool_header = 0; > - > - if ((fp = fopen (filename, "r")) == NULL) > - { > - fprintf (stderr, "cannot open pmu data file: %s\n", filename); > - return 1; > - } > - > - if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_bm_header))) > - { > - fprintf (stderr, "cannot parse pmu data file header: %s\n", filename); > - return 1; > - } > - > - buf = XNEWVEC (char, buflen); > - while (fgets (buf, buflen, fp)) > - { > - gcov_pmu_brm_info_t *brm = XNEW (gcov_pmu_brm_info_t); > - if (!parse_branch_mispredict_line (buf, brm)) > - { > - /* Valid line, add to the array. */ > - brm_infos->brm_count++; > - if (brm_infos->brm_count >= brm_infos->alloc_brm_count) > - { > - /* Do we need to realloc? */ > - brm_infos->brm_array = > - realloc (brm_infos->brm_array, > - 2 * brm_infos->alloc_brm_count); > - if (brm_infos->brm_array == NULL) { > - fprintf (stderr, > - "Cannot allocate memory for br mispredicts.\n"); > - __destroy_pmu_tool_header (tool_header); > - free (buf); > - fclose (fp); > - return 1; > - } > - } > - brm_infos->brm_array[brm_infos->brm_count - 1] = brm; > - } > - else > - /* Delete invalid line. */ > - XDELETE (brm); > - } > - free (buf); > - fclose (fp); > - brm_infos->pmu_tool_header = tool_header; > - return 0; > -} > - > -/* Start the monitoring process using pmu tool. Return 0 on success, > - non-zero otherwise. */ > - > -static int > -pmu_start (void) > -{ > - pid_t pid; > - > - /* no start function */ > - if (!the_pmu_tool_info->tool_details->start_pmu_module) > - return 1; > - > - pid = fork (); > - if (pid == -1) > - { > - /* error condition */ > - fprintf (stderr, "Cannot create PMU profiling process, exiting.\n"); > - return 1; > - } > - else if (pid == 0) > - { > - /* child */ > - pid_t ppid = getppid(); > - char *tmpfile = the_pmu_tool_info->raw_pmu_profile_filename; > - const char **pfmon_args = the_pmu_tool_info->tool_details->arg_array; > - int new_stderr_fd; > - > - /* Redirect stderr from the child process into a separate file. */ > - new_stderr_fd = creat (the_pmu_tool_info->tool_stderr_filename, > - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); > - if (new_stderr_fd != -1) > - dup2 (new_stderr_fd, 2); > - /* The following does an exec and thus is not expected to return. */ > - the_pmu_tool_info->tool_details->start_pmu_module(ppid, tmpfile, > - pfmon_args); > - /* exec returned, an error condition. */ > - fprintf (stderr, "could not create profiling process: %s\n", > - the_pmu_tool_info->tool_details->arg_array[0]); > - _exit (0); > - } > - else > - { > - /* parent */ > - the_pmu_tool_info->pmu_tool_pid = pid; > - return 0; > - } > -} > - > /* Allocate and initialize pmu load latency structure. */ > > static void * > @@ -1205,160 +154,6 @@ init_pmu_branch_mispredict (void) > return (void *)brm_info; > } > > -/* Initialize pmu tool based upon PMU_INFO. Sets the appropriate tool > - type in the global the_pmu_tool_info. */ > - > -static int > -init_pmu_tool (struct gcov_pmu_info *pmu_info) > -{ > - the_pmu_tool_info->pmu_profiling_state = PMU_NONE; > - the_pmu_tool_info->verbose = 0; > - the_pmu_tool_info->tool = PTT_PFMON; /* we support only pfmon */ > - the_pmu_tool_info->pmu_tool_pid = 0; > - the_pmu_tool_info->top_n_address = pmu_info->pmu_top_n_address; > - the_pmu_tool_info->symbolizer_pid = 0; > - the_pmu_tool_info->symbolizer_to_pipefd[0] = -1; > - the_pmu_tool_info->symbolizer_to_pipefd[1] = -1; > - the_pmu_tool_info->symbolizer_from_pipefd[0] = -1; > - the_pmu_tool_info->symbolizer_from_pipefd[1] = -1; > - > - if (parse_pmu_profile_options (pmu_info->pmu_tool)) > - return 1; > - > - if (the_pmu_tool_info->pmu_profiling_state == PMU_ERROR) > - { > - fprintf (stderr, "Unsupported PMU module: %s, disabling PMU profiling.\n", > - pmu_info->pmu_tool); > - return 1; > - } > - > - if (the_pmu_tool_info->tool_details->init_pmu_module) > - /* initialize module */ > - the_pmu_tool_info->pmu_data = > - the_pmu_tool_info->tool_details->init_pmu_module(); > - return 0; > -} > - > -/* Initialize PMU profiling based upon the information passed in > - PMU_INFO and use pmu_profile_filename as the file to store the PMU > - profile. This is called multiple times from libgcov, once per > - object file. We need to make sure to do the necessary > - initialization only the first time. For subsequent invocations it > - behaves as a NOOP. */ > - > -void > -__gcov_init_pmu_profiler (struct gcov_pmu_info *pmu_info) > -{ > - char *raw_pmu_profile_filename; > - char *tool_stderr_filename; > - if (!pmu_info || !pmu_info->pmu_profile_filename || !pmu_info->pmu_tool) > - return; > - > - /* Allocate the global structure on first invocation. */ > - if (!the_pmu_tool_info) > - { > - the_pmu_tool_info = XNEWVEC (struct pmu_tool_info, 1); > - if (!the_pmu_tool_info) > - { > - fprintf (stderr, "Error allocating memory for PMU tool\n"); > - return; > - } > - if (init_pmu_tool (pmu_info)) > - { > - /* Initialization error. */ > - XDELETE (the_pmu_tool_info); > - the_pmu_tool_info = 0; > - return; > - } > - } > - > - switch (the_pmu_tool_info->pmu_profiling_state) > - { > - case PMU_NONE: > - the_pmu_tool_info->pmu_profile_filename = > - strdup (pmu_info->pmu_profile_filename); > - /* Construct an intermediate filename by substituting trailing > - '.gcda' with '.pmud'. */ > - raw_pmu_profile_filename = strdup (pmu_info->pmu_profile_filename); > - if (raw_pmu_profile_filename == NULL) > - { > - fprintf (stderr, "Cannot allocate memory\n"); > - exit (1); > - } > - strcpy (raw_pmu_profile_filename + strlen (raw_pmu_profile_filename) - 4, > - "pmud"); > - > - /* Construct a filename for collecting PMU tool's stderr by > - substituting trailing '.gcda' with '.stderr'. */ > - tool_stderr_filename = > - XNEWVEC (char, strlen (pmu_info->pmu_profile_filename) + 1 + 2); > - strcpy (tool_stderr_filename, pmu_info->pmu_profile_filename); > - strcpy (tool_stderr_filename + strlen (tool_stderr_filename) - 4, > - "stderr"); > - the_pmu_tool_info->raw_pmu_profile_filename = raw_pmu_profile_filename; > - the_pmu_tool_info->tool_stderr_filename = tool_stderr_filename; > - the_pmu_tool_info->pmu_profiling_state = PMU_INITIALIZED; > - break; > - > - case PMU_INITIALIZED: > - case PMU_OFF: > - case PMU_ON: > - case PMU_ERROR: > - break; > - default: > - break; > - } > -} > - > -/* Start PMU profiling. It updates the current state. */ > - > -void > -__gcov_start_pmu_profiler (void) > -{ > - if (!the_pmu_tool_info) > - return; > - > - switch (the_pmu_tool_info->pmu_profiling_state) > - { > - case PMU_INITIALIZED: > - if (!pmu_start ()) > - the_pmu_tool_info->pmu_profiling_state = PMU_ON; > - else > - the_pmu_tool_info->pmu_profiling_state = PMU_ERROR; > - break; > - > - case PMU_NONE: > - /* PMU was not properly initialized, don't attempt start it. */ > - the_pmu_tool_info->pmu_profiling_state = PMU_ERROR; > - break; > - > - case PMU_OFF: > - /* Restarting PMU is not yet supported. */ > - case PMU_ON: > - /* Do nothing. */ > - case PMU_ERROR: > - break; > - > - default: > - break; > - } > -} > - > -/* Stop PMU profiling. Currently it doesn't do anything except > - bookkeeping. */ > - > -void > -__gcov_stop_pmu_profiler (void) > -{ > - if (!the_pmu_tool_info) > - return; > - > - if (the_pmu_tool_info->tool_details->stop_pmu_module) > - the_pmu_tool_info->tool_details->stop_pmu_module(); > - if (the_pmu_tool_info->pmu_profiling_state == PMU_ON) > - the_pmu_tool_info->pmu_profiling_state = PMU_OFF; > -} > - > /* Write the load latency information LL_INFO into the gcda file. */ > > static void > @@ -1400,55 +195,6 @@ gcov_write_branch_mispredict_line (const gcov_pmu_ > gcov_write_string (brm_info->filename); > } > > -/* Write load latency information INFO into the gcda file. The gcda > - file has already been opened and is available for writing. */ > - > -static void > -gcov_write_load_latency_infos (void *info) > -{ > - unsigned i; > - const ll_infos_t *ll_infos = (const ll_infos_t *)info; > - gcov_unsigned_t stamp = 0; /* Don't use stamp as we don't support merge. */ > - /* We don't support merge, and instead always rewrite the file. But > - to rewrite a gcov file we must first read it, however the read > - value is ignored. */ > - gcov_read_unsigned (); > - gcov_rewrite (); > - gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); > - gcov_write_unsigned (stamp); > - if (ll_infos->pmu_tool_header) > - gcov_write_tool_header (ll_infos->pmu_tool_header); > - for (i = 0; i < ll_infos->ll_count; ++i) > - { > - /* Write each line. */ > - gcov_write_ll_line (ll_infos->ll_array[i]); > - } > - gcov_truncate (); > -} > - > -/* Write branch mispredict information INFO into the gcda file. The > - gcda file has already been opened and is available for writing. */ > - > -static void > -gcov_write_branch_mispredict_infos (void *info) > -{ > - unsigned i; > - const brm_infos_t *brm_infos = (const brm_infos_t *)info; > - gcov_unsigned_t stamp = 0; /* Don't use stamp as we don't support merge. */ > - /* We don't support merge, and instead always rewrite the file. */ > - gcov_rewrite (); > - gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); > - gcov_write_unsigned (stamp); > - if (brm_infos->pmu_tool_header) > - gcov_write_tool_header (brm_infos->pmu_tool_header); > - for (i = 0; i < brm_infos->brm_count; ++i) > - { > - /* Write each line. */ > - gcov_write_branch_mispredict_line (brm_infos->brm_array[i]); > - } > - gcov_truncate (); > -} > - > /* Compute TOOL_HEADER length for writing into the gcov file. */ > > static gcov_unsigned_t > @@ -1483,70 +229,4 @@ gcov_write_tool_header (gcov_pmu_tool_header_t *he > gcov_write_string (header->full_header); > } > > - > -/* End PMU profiling. If GCDA_ERROR is non-zero then write profiling data into > - already open gcda file */ > - > -void > -__gcov_end_pmu_profiler (int gcda_error) > -{ > - int pid_status; > - int wait_status; > - pid_t pid; > - pmu_tool_fns *tool_details; > - > - if (!the_pmu_tool_info) > - return; > - > - tool_details = the_pmu_tool_info->tool_details; > - pid = the_pmu_tool_info->pmu_tool_pid; > - if (pid) > - { > - if (tool_debug) > - fprintf (stderr, "terminating PMU profiling process %ld\n", (long)pid); > - kill (pid, SIGTERM); > - if (tool_debug) > - fprintf (stderr, "parent: waiting for pmu process to end\n"); > - wait_status = waitpid (pid, &pid_status, 0); > - if (tool_debug) { > - if (wait_status == pid) > - fprintf (stderr, "Normal exit. Child terminated.\n"); > - else > - fprintf (stderr, "Abnormal exit. child status, %d.\n", pid_status); > - } > - } > - > - if (the_pmu_tool_info->pmu_profiling_state != PMU_OFF) > - { > - /* nothing to do */ > - fprintf (stderr, > - "__gcov_dump_pmu_profile: incorrect pmu state: %d, pid: %ld\n", > - the_pmu_tool_info->pmu_profiling_state, > - (unsigned long)pid); > - return; > - } > - > - if (!tool_details->parse_pmu_output) > - return; > - > - /* Since we are going to parse the output, we also need symbolizer. */ > - if (tool_details->start_symbolizer) > - tool_details->start_symbolizer (getpid ()); > - > - if (!tool_details->parse_pmu_output > - (the_pmu_tool_info->raw_pmu_profile_filename, > - the_pmu_tool_info->pmu_data)) > - { > - if (!gcda_error && tool_details->gcov_write_pmu_data) > - /* Write tool output into the gcda file. */ > - tool_details->gcov_write_pmu_data (the_pmu_tool_info->pmu_data); > - } > - > - if (tool_details->end_symbolizer) > - tool_details->end_symbolizer (); > - > - if (tool_details->cleanup_pmu_data) > - tool_details->cleanup_pmu_data (the_pmu_tool_info->pmu_data); > -} > - > #endif > Index: libgcc/libgcov.c > =================================================================== > --- libgcc/libgcov.c (revision 190135) > +++ libgcc/libgcov.c (working copy) > @@ -463,37 +463,6 @@ gcov_alloc_filename (void) > gi_filename_up = gi_filename + prefix_length; > } > > -/* Stop the pmu profiler and dump pmu profile info into the global file. */ > - > -static void > -pmu_profile_stop (void) > -{ > - const char *pmu_profile_filename = __gcov_pmu_profile_filename; > - const char *pmu_options = __gcov_pmu_profile_options; > - size_t filename_length; > - int gcda_error; > - > - if (!pmu_profile_filename || !pmu_options) > - return; > - > - __gcov_stop_pmu_profiler (); > - > - filename_length = strlen (pmu_profile_filename); > - if (filename_length > gcov_max_filename) > - gcov_max_filename = filename_length; > - /* Allocate and initialize the filename scratch space. */ > - gcov_alloc_filename (); > - GCOV_GET_FILENAME (prefix_length, gcov_prefix_strip, pmu_profile_filename, > - gi_filename_up); > - /* Open the gcda file for writing. We don't support merge yet. */ > - gcda_error = gcov_open_by_filename (gi_filename); > - __gcov_end_pmu_profiler (gcda_error); > - if ((gcda_error = gcov_close ())) > - gcov_error (gcda_error < 0 ? "pmu_profile_stop:%s:Overflow writing\n" : > - "pmu_profile_stop:%s:Error writing\n", > - gi_filename); > -} > - > /* Sort N entries in VALUE_ARRAY in descending order. > Each entry in VALUE_ARRAY has two values. The sorting > is based on the second value. */ > @@ -634,9 +603,6 @@ gcov_exit (void) > if (gcov_dump_complete) > return; > > - /* Stop and write the PMU profile data into the global file. */ > - pmu_profile_stop (); > - > dump_module_info = gcov_exit_init (); > > for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next) > @@ -701,25 +667,11 @@ __gcov_init (struct gcov_info *info) > { > const char *ptr = info->filename; > size_t filename_length = strlen (info->filename); > - struct gcov_pmu_info pmu_info; > > /* Refresh the longest file name information. */ > if (filename_length > gcov_max_filename) > gcov_max_filename = filename_length; > > - /* Initialize the pmu profiler. */ > - pmu_info.pmu_profile_filename = __gcov_pmu_profile_filename; > - pmu_info.pmu_tool = __gcov_pmu_profile_options; > - pmu_info.pmu_top_n_address = __gcov_pmu_top_n_address; > - __gcov_init_pmu_profiler (&pmu_info); > - if (pmu_info.pmu_profile_filename) > - { > - /* Refresh the longest file name information. */ > - filename_length = strlen (pmu_info.pmu_profile_filename); > - if (filename_length > gcov_max_filename) > - gcov_max_filename = filename_length; > - } > - > /* Assign the module ID (starting at 1). */ > info->mod_info->ident = (++gcov_cur_module_id); > gcc_assert (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (GEN_FUNC_GLOBAL_ID ( > @@ -729,8 +681,6 @@ __gcov_init (struct gcov_info *info) > if (!__gcov_list) > { > atexit (gcov_exit); > - /* Start pmu profiler. */ > - __gcov_start_pmu_profiler (); > } > > info->next = __gcov_list; > @@ -746,10 +696,8 @@ __gcov_init (struct gcov_info *info) > void > __gcov_flush (void) > { > - __gcov_stop_pmu_profiler (); > gcov_exit (); > gcov_clear (); > - __gcov_start_pmu_profiler (); > } > > #else /* __GCOV_KERNEL__ */ > > -- > This patch is available for review at http://codereview.appspot.com/6442086
Index: libgcc/pmu-profile.c =================================================================== --- libgcc/pmu-profile.c (revision 190135) +++ libgcc/pmu-profile.c (working copy) @@ -67,169 +67,11 @@ see the files COPYING3 and COPYING.RUNTIME respect #define XDELETEVEC(p) free(p) #define XDELETE(p) free(p) -#define PFMON_CMD "/usr/bin/pfmon" -#define ADDR2LINE_CMD "/usr/bin/addr2line" -#define PMU_TOOL_MAX_ARGS (20) -static char default_addr2line[] = "??:0"; -static const char pfmon_ll_header[] = "# counts %self %cum " - "<10 <32 <64 <256 <1024 >=1024 %wself " - "code addr symbol\n"; -static const char pfmon_bm_header[] = - "# counts %self %cum code addr symbol\n"; - -const char *pfmon_intel_ll_args[PMU_TOOL_MAX_ARGS] = { - PFMON_CMD, - "--aggregate-results", - "--follow-all", - "--with-header", - "--smpl-module=pebs-ll", - "--ld-lat-threshold=4", - "--pebs-ll-dcmiss-code", - "--resolve-addresses", - "-emem_inst_retired:LATENCY_ABOVE_THRESHOLD", - "--long-smpl-periods=10000", - 0 /* terminating NULL must be present */ -}; - -const char *pfmon_amd_ll_args[PMU_TOOL_MAX_ARGS] = { - PFMON_CMD, - "--aggregate-results", - "--follow-all", - "-uk", - "--with-header", - "--smpl-module=ibs", - "--resolve-addresses", - "-eibsop_event:uops", - "--ibs-dcmiss-code", - "--long-smpl-periods=0xffff0", - 0 /* terminating NULL must be present */ -}; - -const char *pfmon_intel_brm_args[PMU_TOOL_MAX_ARGS] = { - PFMON_CMD, - "--aggregate-results", - "--follow-all", - "--with-header", - "--resolve-addresses", - "-eMISPREDICTED_BRANCH_RETIRED", - "--long-smpl-periods=10000", - 0 /* terminating NULL must be present */ -}; - -const char *pfmon_amd_brm_args[PMU_TOOL_MAX_ARGS] = { - PFMON_CMD, - "--aggregate-results", - "--follow-all", - "--with-header", - "--resolve-addresses", - "-eRETIRED_MISPREDICTED_BRANCH_INSTRUCTIONS", - "--long-smpl-periods=10000", - 0 /* terminating NULL must be present */ -}; - -const char *addr2line_args[PMU_TOOL_MAX_ARGS] = { - ADDR2LINE_CMD, - "-e", - 0 /* terminating NULL must be present */ -}; - - -enum pmu_tool_type -{ - PTT_PFMON, - PTT_LAST -}; - -enum pmu_event_type -{ - PET_INTEL_LOAD_LATENCY, - PET_AMD_LOAD_LATENCY, - PET_INTEL_BRANCH_MISPREDICT, - PET_AMD_BRANCH_MISPREDICT, - PET_LAST -}; - -typedef struct pmu_tool_fns { - const char *name; /* name of the pmu tool */ - /* pmu tool commandline argument. */ - const char **arg_array; - /* Initialize pmu module. */ - void *(*init_pmu_module) (void); - /* Start profililing. */ - void (*start_pmu_module) (pid_t ppid, char *tmpfile, const char **args); - /* Stop profililing. */ - void (*stop_pmu_module) (void); - /* How to parse the output generated by the PMU tool. */ - int (*parse_pmu_output) (char *filename, void *pmu_data); - /* How to write parsed pmu data into gcda file. */ - void (*gcov_write_pmu_data) (void *data); - /* How to cleanup any data structure created during parsing. */ - void (*cleanup_pmu_data) (void *data); - /* How to initialize symbolizer for the PPID. */ - int (*start_symbolizer) (pid_t ppid); - void (*end_symbolizer) (void); - char *(*symbolize) (void *addr); -} pmu_tool_fns; - -enum pmu_state -{ - PMU_NONE, /* Not configurated at all. */ - PMU_INITIALIZED, /* Configured and initialized. */ - PMU_ERROR, /* Configuration error. Cannot recover. */ - PMU_ON, /* Currently profiling. */ - PMU_OFF /* Currently stopped, but can be restarted. */ -}; - -enum cpu_vendor_signature -{ - CPU_VENDOR_UKNOWN = 0, - CPU_VENDOR_INTEL = 0x756e6547, /* Genu */ - CPU_VENDOR_AMD = 0x68747541 /* Auth */ -}; - -/* Info about pmu tool during the run time. */ -struct pmu_tool_info -{ - /* Current pmu tool. */ - enum pmu_tool_type tool; - /* Current event. */ - enum pmu_event_type event; - /* filename for storing the pmu profile. */ - char *pmu_profile_filename; - /* Intermediate file where the tool stores the PMU data. */ - char *raw_pmu_profile_filename; - /* Where PMU tool's stderr should be stored. */ - char *tool_stderr_filename; - enum pmu_state pmu_profiling_state; - enum cpu_vendor_signature cpu_vendor; /* as discovered by cpuid */ - pid_t pmu_tool_pid; /* process id of the pmu tool */ - pid_t symbolizer_pid; /* process id of the symbolizer */ - int symbolizer_to_pipefd[2]; /* pipe for writing to the symbolizer */ - int symbolizer_from_pipefd[2]; /* pipe for reading from the symbolizer */ - void *pmu_data; /* an opaque pointer for the tool to store pmu data */ - int verbose; /* turn on additional debugging */ - unsigned top_n_address; /* how many addresses to symbolize */ - pmu_tool_fns *tool_details; /* list of functions how to start/stop/parse */ -}; - -/* Global struct for recordkeeping. */ -static struct pmu_tool_info *the_pmu_tool_info; - -/* Additional info is printed if these are non-zero. */ -static int tool_debug = 0; -static int sym_debug = 0; - -static int parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info); -static int parse_branch_mispredict_line (char *line, - gcov_pmu_brm_info_t *brm_info); static unsigned convert_pct_to_unsigned (float pct); -static void start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args); static void *init_pmu_load_latency (void); static void *init_pmu_branch_mispredict (void); static void destroy_load_latency_infos (void *info); static void destroy_branch_mispredict_infos (void *info); -static int parse_pfmon_load_latency (char *filename, void *pmu_data); -static int parse_pfmon_branch_mispredicts (char *filename, void *pmu_data); static gcov_unsigned_t gcov_tag_pmu_tool_header_length (gcov_pmu_tool_header_t *header); static void gcov_write_tool_header (gcov_pmu_tool_header_t *header); @@ -238,456 +80,7 @@ static void gcov_write_branch_mispredict_infos (vo static void gcov_write_ll_line (const gcov_pmu_ll_info_t *ll_info); static void gcov_write_branch_mispredict_line (const gcov_pmu_brm_info_t *brm_info); -static int start_addr2line_symbolizer (pid_t pid); -static void end_addr2line_symbolizer (void); -static char *symbolize_addr2line (void *p); -static void reset_symbolizer_parent_pipes (void); -static void reset_symbolizer_child_pipes (void); -/* parse and cache relevant tool info. */ -static int parse_pmu_profile_options (const char *options); -static gcov_pmu_tool_header_t *parse_pfmon_tool_header (FILE *fp, - const char *end_header); - -/* How to access the necessary functions for the PMU tools. */ -pmu_tool_fns all_pmu_tool_fns[PTT_LAST][PET_LAST] = { - { - { - "intel-load-latency", /* name */ - pfmon_intel_ll_args, /* tool args */ - init_pmu_load_latency, /* initialization */ - start_pfmon_module, /* start */ - 0, /* stop */ - parse_pfmon_load_latency, /* parse */ - gcov_write_load_latency_infos, /* write */ - destroy_load_latency_infos, /* cleanup */ - start_addr2line_symbolizer, /* start symbolizer */ - end_addr2line_symbolizer, /* end symbolizer */ - symbolize_addr2line, /* symbolize */ - }, - { - "amd-load-latency", /* name */ - pfmon_amd_ll_args, /* tool args */ - init_pmu_load_latency, /* initialization */ - start_pfmon_module, /* start */ - 0, /* stop */ - parse_pfmon_load_latency, /* parse */ - gcov_write_load_latency_infos, /* write */ - destroy_load_latency_infos, /* cleanup */ - start_addr2line_symbolizer, /* start symbolizer */ - end_addr2line_symbolizer, /* end symbolizer */ - symbolize_addr2line, /* symbolize */ - }, - { - "intel-branch-mispredict", /* name */ - pfmon_intel_brm_args, /* tool args */ - init_pmu_branch_mispredict, /* initialization */ - start_pfmon_module, /* start */ - 0, /* stop */ - parse_pfmon_branch_mispredicts, /* parse */ - gcov_write_branch_mispredict_infos,/* write */ - destroy_branch_mispredict_infos, /* cleanup */ - start_addr2line_symbolizer, /* start symbolizer */ - end_addr2line_symbolizer, /* end symbolizer */ - symbolize_addr2line, /* symbolize */ - }, - { - "amd-branch-mispredict", /* name */ - pfmon_amd_brm_args, /* tool args */ - init_pmu_branch_mispredict, /* initialization */ - start_pfmon_module, /* start */ - 0, /* stop */ - parse_pfmon_branch_mispredicts, /* parse */ - gcov_write_branch_mispredict_infos,/* write */ - destroy_branch_mispredict_infos, /* cleanup */ - start_addr2line_symbolizer, /* start symbolizer */ - end_addr2line_symbolizer, /* end symbolizer */ - symbolize_addr2line, /* symbolize */ - } - } -}; - -/* Determine the CPU vendor. Currently only distinguishes x86 based - cpus where the vendor is either Intel or AMD. Returns one of the - enum cpu_vendor_signatures. */ - -static unsigned int -get_x86cpu_vendor (void) -{ - unsigned int vendor = CPU_VENDOR_UKNOWN; - -#if (defined (__x86_64__) || defined (__i386__)) - if (__get_cpuid_max (0, &vendor) < 1) - return CPU_VENDOR_UKNOWN; /* Cannot determine cpu type. */ -#endif - - if (vendor == CPU_VENDOR_INTEL || vendor == CPU_VENDOR_AMD) - return vendor; - else - return CPU_VENDOR_UKNOWN; -} - - -/* Parse PMU tool option string provided on the command line and store - information in global structure. Return 0 on success, otherwise - return 1. Any changes to this should be synced with - check_pmu_profile_options() which does compile time check. */ - -static int -parse_pmu_profile_options (const char *options) -{ - enum pmu_tool_type ptt = the_pmu_tool_info->tool; - enum pmu_event_type pet = PET_LAST; - const char *pmutool_path; - the_pmu_tool_info->cpu_vendor = get_x86cpu_vendor (); - /* Determine the platform we are running on. */ - if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_UKNOWN) - { - /* Cpuid failed or uknown vendor. */ - the_pmu_tool_info->pmu_profiling_state = PMU_ERROR; - return 1; - } - - /* Validate the options. */ - if (strcmp(options, "load-latency") && - strcmp(options, "load-latency-verbose") && - strcmp(options, "branch-mispredict") && - strcmp(options, "branch-mispredict-verbose")) - return 1; - - /* Check if are aksed to collect load latency PMU data. */ - if (!strcmp(options, "load-latency") || - !strcmp(options, "load-latency-verbose")) - { - if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL) - pet = PET_INTEL_LOAD_LATENCY; - else - pet = PET_AMD_LOAD_LATENCY; - if (!strcmp(options, "load-latency-verbose")) - the_pmu_tool_info->verbose = 1; - } - - /* Check if are aksed to collect branch mispredict PMU data. */ - if (!strcmp(options, "branch-mispredict") || - !strcmp(options, "branch-mispredict-verbose")) - { - if (the_pmu_tool_info->cpu_vendor == CPU_VENDOR_INTEL) - pet = PET_INTEL_BRANCH_MISPREDICT; - else - pet = PET_AMD_BRANCH_MISPREDICT; - if (!strcmp(options, "branch-mispredict-verbose")) - the_pmu_tool_info->verbose = 1; - } - - the_pmu_tool_info->tool_details = &all_pmu_tool_fns[ptt][pet]; - the_pmu_tool_info->event = pet; - - /* Allow users to override the default tool path. */ - pmutool_path = getenv ("GCOV_PMUTOOL_PATH"); - if (pmutool_path && strlen (pmutool_path)) - the_pmu_tool_info->tool_details->arg_array[0] = pmutool_path; - - return 0; -} - -/* Do the initialization of addr2line symbolizer for the process id - given by TASK_PID. It forks an addr2line process and creates two - pipes where addresses can be written and source_filename:line_num - entries can be read. Returns 0 on success, non-zero otherwise. */ - -static int -start_addr2line_symbolizer (pid_t task_pid) -{ - pid_t pid; - char *addr2line_path; - - /* Allow users to override the default addr2line path. */ - addr2line_path = getenv ("GCOV_ADDR2LINE_PATH"); - if (addr2line_path && strlen (addr2line_path)) - addr2line_args[0] = addr2line_path; - - if (pipe (the_pmu_tool_info->symbolizer_from_pipefd) == -1) - { - fprintf (stderr, "Cannot create symbolizer write pipe.\n"); - return 1; - } - if (pipe (the_pmu_tool_info->symbolizer_to_pipefd) == -1) - { - fprintf (stderr, "Cannot create symbolizer read pipe.\n"); - return 1; - } - - pid = fork (); - if (pid == -1) - { - /* error condition */ - fprintf (stderr, "Cannot create symbolizer process.\n"); - reset_symbolizer_parent_pipes (); - reset_symbolizer_child_pipes (); - return 1; - } - - if (pid == 0) - { - /* child does an exec and then connects to/from the pipe */ - unsigned n_args = 0; - char proc_exe_buf[128]; - int new_write_fd, new_read_fd; - int i; - - /* Go over the current addr2line args. */ - for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i) - n_args++; - - /* We are going to add one more arg for the /proc/pid/exe */ - if (n_args >= (PMU_TOOL_MAX_ARGS - 1)) - { - fprintf (stderr, "too many addr2line args: %d\n", n_args); - _exit (0); - } - snprintf (proc_exe_buf, sizeof (proc_exe_buf), "/proc/%d/exe", - task_pid); - - /* Add the extra arg for the process id. */ - addr2line_args[n_args] = proc_exe_buf; - n_args++; - - addr2line_args[n_args] = (const char *)NULL; /* terminating NULL */ - - if (sym_debug) - { - fprintf (stderr, "addr2line args:"); - for (i = 0; i < PMU_TOOL_MAX_ARGS && addr2line_args[i]; ++i) - fprintf (stderr, " %s", addr2line_args[i]); - fprintf (stderr, "\n"); - } - - /* Close unused ends of the two pipes. */ - reset_symbolizer_child_pipes (); - - /* Connect the pipes to stdin/stdout of the child process. */ - new_read_fd = dup2 (the_pmu_tool_info->symbolizer_to_pipefd[0], 0); - new_write_fd = dup2 (the_pmu_tool_info->symbolizer_from_pipefd[1], 1); - if (new_read_fd == -1 || new_write_fd == -1) - { - fprintf (stderr, "could not dup symbolizer fds\n"); - reset_symbolizer_parent_pipes (); - reset_symbolizer_child_pipes (); - _exit (0); - } - the_pmu_tool_info->symbolizer_to_pipefd[0] = new_read_fd; - the_pmu_tool_info->symbolizer_from_pipefd[1] = new_write_fd; - - /* Do execve with NULL env. */ - execve (addr2line_args[0], (char * const*)addr2line_args, - (char * const*)NULL); - /* exec returned, an error condition. */ - fprintf (stderr, "could not create symbolizer process: %s\n", - addr2line_args[0]); - reset_symbolizer_parent_pipes (); - reset_symbolizer_child_pipes (); - _exit (0); - } - else - { - /* parent */ - the_pmu_tool_info->symbolizer_pid = pid; - /* Close unused ends of the two pipes. */ - reset_symbolizer_parent_pipes (); - return 0; - } - return 0; -} - -/* Close unused write end of the from-pipe and read end of the - to-pipe. */ - -static void -reset_symbolizer_parent_pipes (void) -{ - if (the_pmu_tool_info->symbolizer_from_pipefd[1] != -1) - { - close (the_pmu_tool_info->symbolizer_from_pipefd[1]); - the_pmu_tool_info->symbolizer_from_pipefd[1] = -1; - } - if (the_pmu_tool_info->symbolizer_to_pipefd[0] != -1) - { - close (the_pmu_tool_info->symbolizer_to_pipefd[0]); - the_pmu_tool_info->symbolizer_to_pipefd[0] = -1; - } -} - -/* Close unused write end of the to-pipe and read end of the - from-pipe. */ - -static void -reset_symbolizer_child_pipes (void) -{ - if (the_pmu_tool_info->symbolizer_to_pipefd[1] != -1) - { - close (the_pmu_tool_info->symbolizer_to_pipefd[1]); - the_pmu_tool_info->symbolizer_to_pipefd[1] = -1; - } - if (the_pmu_tool_info->symbolizer_from_pipefd[0] != -1) - { - close (the_pmu_tool_info->symbolizer_from_pipefd[0]); - the_pmu_tool_info->symbolizer_from_pipefd[0] = -1; - } -} - - -/* Perform cleanup for the symbolizer process. */ - -static void -end_addr2line_symbolizer (void) -{ - int pid_status; - int wait_status; - pid_t pid = the_pmu_tool_info->symbolizer_pid; - - /* Symbolizer was not running. */ - if (!pid) - return; - - reset_symbolizer_parent_pipes (); - reset_symbolizer_child_pipes (); - kill (pid, SIGTERM); - wait_status = waitpid (pid, &pid_status, 0); - if (sym_debug) - { - if (wait_status == pid) - fprintf (stderr, "Normal exit. symbolizer terminated.\n"); - else - fprintf (stderr, "Abnormal exit. symbolizer status, %d.\n", pid_status); - } - the_pmu_tool_info->symbolizer_pid = 0; /* Symoblizer no longer running. */ -} - - -/* Given an address ADDR, return a string containing - source_filename:line_num entries. */ - -static char * -symbolize_addr2line (void *addr) -{ - char buf[32]; /* holds the ascii version of address */ - int write_count; - int read_count; - char *srcfile_linenum; - size_t max_length = 1024; - - if (!the_pmu_tool_info->symbolizer_pid) - return default_addr2line; /* symbolizer is not running */ - - write_count = snprintf (buf, sizeof (buf), "%p\n", addr); - - /* Write the address into the pipe. */ - if (write (the_pmu_tool_info->symbolizer_to_pipefd[1], buf, write_count) - < write_count) - { - if (sym_debug) - fprintf (stderr, "Cannot write symbolizer pipe.\n"); - return default_addr2line; - } - - srcfile_linenum = XNEWVEC (char, max_length); - read_count = read (the_pmu_tool_info->symbolizer_from_pipefd[0], - srcfile_linenum, max_length); - if (read_count == -1) - { - if (sym_debug) - fprintf (stderr, "Cannot read symbolizer pipe.\n"); - XDELETEVEC (srcfile_linenum); - return default_addr2line; - } - - srcfile_linenum[read_count] = 0; - if (sym_debug) - fprintf (stderr, "symbolizer: for address %p, read_count %d, got %s\n", - addr, read_count, srcfile_linenum); - return srcfile_linenum; -} - -/* Start monitoring PPID process via pfmon tool using TMPFILE as a - file to store the raw data and using PFMON_ARGS as the command line - arguments. */ - -static void -start_pfmon_module (pid_t ppid, char *tmpfile, const char **pfmon_args) -{ - int i; - unsigned int n_args = 0; - unsigned n_chars; - char pid_buf[64]; - char filename_buf[1024]; - char top_n_buf[24]; - unsigned extra_args; - - /* Go over the current pfmon args */ - for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i) - n_args++; - - if (the_pmu_tool_info->verbose) - extra_args = 4; /* account for additional --verbose */ - else - extra_args = 3; - - /* We are going to add args. */ - if (n_args >= (PMU_TOOL_MAX_ARGS - extra_args)) - { - fprintf (stderr, "too many pfmon args: %d\n", n_args); - _exit (0); - } - - n_chars = snprintf (pid_buf, sizeof (pid_buf), "--attach-task=%ld", - (long)ppid); - if (n_chars >= sizeof (pid_buf)) - { - fprintf (stderr, "pfmon task id too long: %s\n", pid_buf); - return; - } - pfmon_args[n_args] = pid_buf; - n_args++; - - n_chars = snprintf (filename_buf, sizeof (filename_buf), "--smpl-outfile=%s", - tmpfile); - if (n_chars >= sizeof (filename_buf)) - { - fprintf (stderr, "pfmon filename too long: %s\n", filename_buf); - return; - } - pfmon_args[n_args] = filename_buf; - n_args++; - - n_chars = snprintf (top_n_buf, sizeof (top_n_buf), "--smpl-show-top=%d", - the_pmu_tool_info->top_n_address); - if (n_chars >= sizeof (top_n_buf)) - { - fprintf (stderr, "pfmon option too long: %s\n", top_n_buf); - return; - } - pfmon_args[n_args] = top_n_buf; - n_args++; - - if (the_pmu_tool_info->verbose) { - /* Add --verbose as well. */ - pfmon_args[n_args] = "--verbose"; - n_args++; - } - pfmon_args[n_args] = (char *)NULL; - - if (tool_debug) - { - fprintf (stderr, "pfmon args:"); - for (i = 0; i < PMU_TOOL_MAX_ARGS && pfmon_args[i]; ++i) - fprintf (stderr, " %s", pfmon_args[i]); - fprintf (stderr, "\n"); - } - /* Do execve with NULL env. */ - execve (pfmon_args[0], (char *const *)pfmon_args, (char * const*)NULL); - /* does not return */ -} - /* Convert a fractional PCT to an unsigned integer after muliplying by 100. */ @@ -697,147 +90,6 @@ convert_pct_to_unsigned (float pct) return (unsigned)(pct * 100.0f); } -/* Parse the load latency info pointed by LINE and save it into - LL_INFO. Returns 0 if the line was parsed successfully, non-zero - otherwise. - - An example header+line look like these: - "counts %self %cum <10 <32 <64 <256 <1024 >=1024 - %wself code addr symbol" - "218 24.06% 24.06% 100.00% 0.00% 0.00% 0.00% 0.00% 0.00% 22.70% - 0x0000000000413e75 CalcSSIM(...)+965</tmp/psnr>" -*/ - -static int -parse_load_latency_line (char *line, gcov_pmu_ll_info_t *ll_info) -{ - unsigned counts; - /* These are percentages parsed as floats, but then converted to - integers after multiplying by 100. */ - float self, cum, lt_10, lt_32, lt_64, lt_256, lt_1024, gt_1024, wself; - long unsigned int p; - int n_values; - pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details; - - n_values = sscanf (line, "%u%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%f%%%lx", - &counts, &self, &cum, <_10, <_32, <_64, <_256, - <_1024, >_1024, &wself, &p); - if (n_values != 11) - return 1; - - /* Values read successfully. Do the assignment after converting - * percentages into ints. */ - ll_info->counts = counts; - ll_info->self = convert_pct_to_unsigned (self); - ll_info->cum = convert_pct_to_unsigned (cum); - ll_info->lt_10 = convert_pct_to_unsigned (lt_10); - ll_info->lt_32 = convert_pct_to_unsigned (lt_32); - ll_info->lt_64 = convert_pct_to_unsigned (lt_64); - ll_info->lt_256 = convert_pct_to_unsigned (lt_256); - ll_info->lt_1024 = convert_pct_to_unsigned (lt_1024); - ll_info->gt_1024 = convert_pct_to_unsigned (gt_1024); - ll_info->wself = convert_pct_to_unsigned (wself); - ll_info->code_addr = p; - - /* Run the raw address through the symbolizer. */ - if (tool_details->symbolize) - { - char *sym_info = tool_details->symbolize ((void *)p); - /* sym_info is of the form src_filename:linenum. Descriminator is - currently not supported by addr2line. */ - char *sep = strchr (sym_info, ':'); - if (!sep) - { - /* Assume entire string is srcfile. */ - ll_info->filename = (char *)sym_info; - ll_info->line = 0; - } - else - { - /* Terminate the filename string at the separator. */ - *sep = 0; - ll_info->filename = (char *)sym_info; - /* Convert rest of the sym info to a line number. */ - ll_info->line = atol (sep+1); - } - ll_info->discriminator = 0; - } - else - { - /* No symbolizer available. */ - ll_info->filename = NULL; - ll_info->line = 0; - ll_info->discriminator = 0; - } - return 0; -} - -/* Parse the branch mispredict info pointed by LINE and save it into - BRM_INFO. Returns 0 if the line was parsed successfully, non-zero - otherwise. - - An example header+line look like these: - "counts %self %cum code addr symbol" - "6869 37.67% 37.67% 0x00000000004007e5 sum(std::vector<int*, - std::allocator<int*> > const&)+51</root/tmp/array>" -*/ - -static int -parse_branch_mispredict_line (char *line, gcov_pmu_brm_info_t *brm_info) -{ - unsigned counts; - /* These are percentages parsed as floats, but then converted to - ints after multiplying by 100. */ - float self, cum; - long unsigned int p; - int n_values; - pmu_tool_fns *tool_details = the_pmu_tool_info->tool_details; - - n_values = sscanf (line, "%u%f%%%f%%%lx", - &counts, &self, &cum, &p); - if (n_values != 4) - return 1; - - /* Values read successfully. Do the assignment after converting - * percentages into ints. */ - brm_info->counts = counts; - brm_info->self = convert_pct_to_unsigned (self); - brm_info->cum = convert_pct_to_unsigned (cum); - brm_info->code_addr = p; - - /* Run the raw address through the symbolizer. */ - if (tool_details->symbolize) - { - char *sym_info = tool_details->symbolize ((void *)p); - /* sym_info is of the form src_filename:linenum. Descriminator is - currently not supported by addr2line. */ - char *sep = strchr (sym_info, ':'); - if (!sep) - { - /* Assume entire string is srcfile. */ - brm_info->filename = sym_info; - brm_info->line = 0; - } - else - { - /* Terminate the filename string at the separator. */ - *sep = 0; - brm_info->filename = sym_info; - /* Convert rest of the sym info to a line number. */ - brm_info->line = atol (sep+1); - } - brm_info->discriminator = 0; - } - else - { - /* No symbolizer available. */ - brm_info->filename = NULL; - brm_info->line = 0; - brm_info->discriminator = 0; - } - return 0; -} - /* Delete load latency info structures INFO. */ static void @@ -876,309 +128,6 @@ destroy_branch_mispredict_infos (void *info) brm_infos->brm_count = 0; } -/* Parse FILENAME for load latency lines into a structure - PMU_DATA. Returns 0 on on success. Returns non-zero on - failure. */ - -static int -parse_pfmon_load_latency (char *filename, void *pmu_data) -{ - FILE *fp; - size_t buflen = 2*1024; - char *buf; - ll_infos_t *load_latency_infos = (ll_infos_t *)pmu_data; - gcov_pmu_tool_header_t *tool_header = 0; - - if ((fp = fopen (filename, "r")) == NULL) - { - fprintf (stderr, "cannot open pmu data file: %s\n", filename); - return 1; - } - - if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_ll_header))) - { - fprintf (stderr, "cannot parse pmu data file header: %s\n", filename); - return 1; - } - - buf = XNEWVEC (char, buflen); - while (fgets (buf, buflen, fp)) - { - gcov_pmu_ll_info_t *ll_info = XNEW (gcov_pmu_ll_info_t); - if (!parse_load_latency_line (buf, ll_info)) - { - /* valid line, add to the array */ - load_latency_infos->ll_count++; - if (load_latency_infos->ll_count >= - load_latency_infos->alloc_ll_count) - { - /* need to realloc */ - load_latency_infos->ll_array = - realloc (load_latency_infos->ll_array, - 2 * load_latency_infos->alloc_ll_count); - if (load_latency_infos->ll_array == NULL) - { - fprintf (stderr, "Cannot allocate load latency memory.\n"); - __destroy_pmu_tool_header (tool_header); - free (buf); - fclose (fp); - return 1; - } - } - load_latency_infos->ll_array[load_latency_infos->ll_count - 1] = - ll_info; - } - else - /* Delete invalid line. */ - XDELETE (ll_info); - } - free (buf); - fclose (fp); - load_latency_infos->pmu_tool_header = tool_header; - return 0; -} - -/* Parse open file FP until END_HEADER is seen. The data matching - gcov_pmu_tool_header_t fields is saved and returned in a new - struct. In case of failure, it returns NULL. */ - -static gcov_pmu_tool_header_t * -parse_pfmon_tool_header (FILE *fp, const char *end_header) -{ - static const char tag_hostname[] = "# hostname: "; - static const char tag_kversion[] = "# kernel version: "; - static const char tag_hostcpu[] = "# host CPUs: "; - static const char tag_column_desc_start[] = "# description of columns:"; - static const char tag_column_desc_end[] = - "# other columns are self-explanatory"; - size_t buflen = 4*1024; - char *buf, *buf_start, *buf_end; - gcov_pmu_tool_header_t *tool_header = XNEWVEC (gcov_pmu_tool_header_t, 1); - char *hostname = 0; - char *kversion = 0; - char *hostcpu = 0; - char *column_description = 0; - char *column_desc_start = 0; - char *column_desc_end = 0; - const char *column_header = 0; - int got_hostname = 0; - int got_kversion = 0 ; - int got_hostcpu = 0; - int got_end_header = 0; - int got_column_description = 0; - - buf = XNEWVEC (char, buflen); - buf_start = buf; - buf_end = buf + buflen; - while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp)) - { - if (strncmp (end_header, buf, buf_end - buf) == 0) - { - got_end_header = 1; - break; - } - if (!got_hostname && - strncmp (buf, tag_hostname, strlen (tag_hostname)) == 0) - { - size_t len = strlen (buf) - strlen (tag_hostname); - hostname = XNEWVEC (char, len); - memcpy (hostname, buf + strlen (tag_hostname), len); - hostname[len - 1] = 0; - tool_header->hostname = hostname; - got_hostname = 1; - } - - if (!got_kversion && - strncmp (buf, tag_kversion, strlen (tag_kversion)) == 0) - { - size_t len = strlen (buf) - strlen (tag_kversion); - kversion = XNEWVEC (char, len); - memcpy (kversion, buf + strlen (tag_kversion), len); - kversion[len - 1] = 0; - tool_header->kernel_version = kversion; - got_kversion = 1; - } - - if (!got_hostcpu && - strncmp (buf, tag_hostcpu, strlen (tag_hostcpu)) == 0) - { - size_t len = strlen (buf) - strlen (tag_hostcpu); - hostcpu = XNEWVEC (char, len); - memcpy (hostcpu, buf + strlen (tag_hostcpu), len); - hostcpu[len - 1] = 0; - tool_header->host_cpu = hostcpu; - got_hostcpu = 1; - } - if (!got_column_description && - strncmp (buf, tag_column_desc_start, strlen (tag_column_desc_start)) - == 0) - { - column_desc_start = buf; - column_desc_end = 0; - /* Continue reading until end of the column descriptor. */ - while (buf < (buf_end - 1) && fgets (buf, buf_end - buf, fp)) - { - if (strncmp (buf, tag_column_desc_end, - strlen (tag_column_desc_end)) == 0) - { - column_desc_end = buf + strlen (tag_column_desc_end); - break; - } - buf += strlen (buf); - } - if (column_desc_end) - { - /* Found the end, copy it into a new string. */ - column_description = XNEWVEC (char, column_desc_end - - column_desc_start + 1); - got_column_description = 1; - strcpy (column_description, column_desc_start); - tool_header->column_description = column_description; - } - } - buf += strlen (buf); - } - - /* If we are missing any of the fields, return NULL. */ - if (!got_end_header || !got_hostname || !got_kversion || !got_hostcpu - || !got_column_description) - { - free (hostname); - free (kversion); - free (hostcpu); - free (column_description); - free (buf_start); - free (tool_header); - return NULL; - } - - switch (the_pmu_tool_info->event) - { - case PET_INTEL_LOAD_LATENCY: - case PET_AMD_LOAD_LATENCY: - column_header = pfmon_ll_header; - break; - case PET_INTEL_BRANCH_MISPREDICT: - case PET_AMD_BRANCH_MISPREDICT: - column_header = pfmon_bm_header; - break; - default: - break; - } - tool_header->column_header = strdup (column_header); - tool_header->full_header = buf_start; - return tool_header; -} - - -/* Parse FILENAME for branch mispredict lines into a structure - PMU_DATA. Returns 0 on on success. Returns non-zero on - failure. */ - -static int -parse_pfmon_branch_mispredicts (char *filename, void *pmu_data) -{ - FILE *fp; - size_t buflen = 2*1024; - char *buf; - brm_infos_t *brm_infos = (brm_infos_t *)pmu_data; - gcov_pmu_tool_header_t *tool_header = 0; - - if ((fp = fopen (filename, "r")) == NULL) - { - fprintf (stderr, "cannot open pmu data file: %s\n", filename); - return 1; - } - - if (!(tool_header = parse_pfmon_tool_header (fp, pfmon_bm_header))) - { - fprintf (stderr, "cannot parse pmu data file header: %s\n", filename); - return 1; - } - - buf = XNEWVEC (char, buflen); - while (fgets (buf, buflen, fp)) - { - gcov_pmu_brm_info_t *brm = XNEW (gcov_pmu_brm_info_t); - if (!parse_branch_mispredict_line (buf, brm)) - { - /* Valid line, add to the array. */ - brm_infos->brm_count++; - if (brm_infos->brm_count >= brm_infos->alloc_brm_count) - { - /* Do we need to realloc? */ - brm_infos->brm_array = - realloc (brm_infos->brm_array, - 2 * brm_infos->alloc_brm_count); - if (brm_infos->brm_array == NULL) { - fprintf (stderr, - "Cannot allocate memory for br mispredicts.\n"); - __destroy_pmu_tool_header (tool_header); - free (buf); - fclose (fp); - return 1; - } - } - brm_infos->brm_array[brm_infos->brm_count - 1] = brm; - } - else - /* Delete invalid line. */ - XDELETE (brm); - } - free (buf); - fclose (fp); - brm_infos->pmu_tool_header = tool_header; - return 0; -} - -/* Start the monitoring process using pmu tool. Return 0 on success, - non-zero otherwise. */ - -static int -pmu_start (void) -{ - pid_t pid; - - /* no start function */ - if (!the_pmu_tool_info->tool_details->start_pmu_module) - return 1; - - pid = fork (); - if (pid == -1) - { - /* error condition */ - fprintf (stderr, "Cannot create PMU profiling process, exiting.\n"); - return 1; - } - else if (pid == 0) - { - /* child */ - pid_t ppid = getppid(); - char *tmpfile = the_pmu_tool_info->raw_pmu_profile_filename; - const char **pfmon_args = the_pmu_tool_info->tool_details->arg_array; - int new_stderr_fd; - - /* Redirect stderr from the child process into a separate file. */ - new_stderr_fd = creat (the_pmu_tool_info->tool_stderr_filename, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if (new_stderr_fd != -1) - dup2 (new_stderr_fd, 2); - /* The following does an exec and thus is not expected to return. */ - the_pmu_tool_info->tool_details->start_pmu_module(ppid, tmpfile, - pfmon_args); - /* exec returned, an error condition. */ - fprintf (stderr, "could not create profiling process: %s\n", - the_pmu_tool_info->tool_details->arg_array[0]); - _exit (0); - } - else - { - /* parent */ - the_pmu_tool_info->pmu_tool_pid = pid; - return 0; - } -} - /* Allocate and initialize pmu load latency structure. */ static void * @@ -1205,160 +154,6 @@ init_pmu_branch_mispredict (void) return (void *)brm_info; } -/* Initialize pmu tool based upon PMU_INFO. Sets the appropriate tool - type in the global the_pmu_tool_info. */ - -static int -init_pmu_tool (struct gcov_pmu_info *pmu_info) -{ - the_pmu_tool_info->pmu_profiling_state = PMU_NONE; - the_pmu_tool_info->verbose = 0; - the_pmu_tool_info->tool = PTT_PFMON; /* we support only pfmon */ - the_pmu_tool_info->pmu_tool_pid = 0; - the_pmu_tool_info->top_n_address = pmu_info->pmu_top_n_address; - the_pmu_tool_info->symbolizer_pid = 0; - the_pmu_tool_info->symbolizer_to_pipefd[0] = -1; - the_pmu_tool_info->symbolizer_to_pipefd[1] = -1; - the_pmu_tool_info->symbolizer_from_pipefd[0] = -1; - the_pmu_tool_info->symbolizer_from_pipefd[1] = -1; - - if (parse_pmu_profile_options (pmu_info->pmu_tool)) - return 1; - - if (the_pmu_tool_info->pmu_profiling_state == PMU_ERROR) - { - fprintf (stderr, "Unsupported PMU module: %s, disabling PMU profiling.\n", - pmu_info->pmu_tool); - return 1; - } - - if (the_pmu_tool_info->tool_details->init_pmu_module) - /* initialize module */ - the_pmu_tool_info->pmu_data = - the_pmu_tool_info->tool_details->init_pmu_module(); - return 0; -} - -/* Initialize PMU profiling based upon the information passed in - PMU_INFO and use pmu_profile_filename as the file to store the PMU - profile. This is called multiple times from libgcov, once per - object file. We need to make sure to do the necessary - initialization only the first time. For subsequent invocations it - behaves as a NOOP. */ - -void -__gcov_init_pmu_profiler (struct gcov_pmu_info *pmu_info) -{ - char *raw_pmu_profile_filename; - char *tool_stderr_filename; - if (!pmu_info || !pmu_info->pmu_profile_filename || !pmu_info->pmu_tool) - return; - - /* Allocate the global structure on first invocation. */ - if (!the_pmu_tool_info) - { - the_pmu_tool_info = XNEWVEC (struct pmu_tool_info, 1); - if (!the_pmu_tool_info) - { - fprintf (stderr, "Error allocating memory for PMU tool\n"); - return; - } - if (init_pmu_tool (pmu_info)) - { - /* Initialization error. */ - XDELETE (the_pmu_tool_info); - the_pmu_tool_info = 0; - return; - } - } - - switch (the_pmu_tool_info->pmu_profiling_state) - { - case PMU_NONE: - the_pmu_tool_info->pmu_profile_filename = - strdup (pmu_info->pmu_profile_filename); - /* Construct an intermediate filename by substituting trailing - '.gcda' with '.pmud'. */ - raw_pmu_profile_filename = strdup (pmu_info->pmu_profile_filename); - if (raw_pmu_profile_filename == NULL) - { - fprintf (stderr, "Cannot allocate memory\n"); - exit (1); - } - strcpy (raw_pmu_profile_filename + strlen (raw_pmu_profile_filename) - 4, - "pmud"); - - /* Construct a filename for collecting PMU tool's stderr by - substituting trailing '.gcda' with '.stderr'. */ - tool_stderr_filename = - XNEWVEC (char, strlen (pmu_info->pmu_profile_filename) + 1 + 2); - strcpy (tool_stderr_filename, pmu_info->pmu_profile_filename); - strcpy (tool_stderr_filename + strlen (tool_stderr_filename) - 4, - "stderr"); - the_pmu_tool_info->raw_pmu_profile_filename = raw_pmu_profile_filename; - the_pmu_tool_info->tool_stderr_filename = tool_stderr_filename; - the_pmu_tool_info->pmu_profiling_state = PMU_INITIALIZED; - break; - - case PMU_INITIALIZED: - case PMU_OFF: - case PMU_ON: - case PMU_ERROR: - break; - default: - break; - } -} - -/* Start PMU profiling. It updates the current state. */ - -void -__gcov_start_pmu_profiler (void) -{ - if (!the_pmu_tool_info) - return; - - switch (the_pmu_tool_info->pmu_profiling_state) - { - case PMU_INITIALIZED: - if (!pmu_start ()) - the_pmu_tool_info->pmu_profiling_state = PMU_ON; - else - the_pmu_tool_info->pmu_profiling_state = PMU_ERROR; - break; - - case PMU_NONE: - /* PMU was not properly initialized, don't attempt start it. */ - the_pmu_tool_info->pmu_profiling_state = PMU_ERROR; - break; - - case PMU_OFF: - /* Restarting PMU is not yet supported. */ - case PMU_ON: - /* Do nothing. */ - case PMU_ERROR: - break; - - default: - break; - } -} - -/* Stop PMU profiling. Currently it doesn't do anything except - bookkeeping. */ - -void -__gcov_stop_pmu_profiler (void) -{ - if (!the_pmu_tool_info) - return; - - if (the_pmu_tool_info->tool_details->stop_pmu_module) - the_pmu_tool_info->tool_details->stop_pmu_module(); - if (the_pmu_tool_info->pmu_profiling_state == PMU_ON) - the_pmu_tool_info->pmu_profiling_state = PMU_OFF; -} - /* Write the load latency information LL_INFO into the gcda file. */ static void @@ -1400,55 +195,6 @@ gcov_write_branch_mispredict_line (const gcov_pmu_ gcov_write_string (brm_info->filename); } -/* Write load latency information INFO into the gcda file. The gcda - file has already been opened and is available for writing. */ - -static void -gcov_write_load_latency_infos (void *info) -{ - unsigned i; - const ll_infos_t *ll_infos = (const ll_infos_t *)info; - gcov_unsigned_t stamp = 0; /* Don't use stamp as we don't support merge. */ - /* We don't support merge, and instead always rewrite the file. But - to rewrite a gcov file we must first read it, however the read - value is ignored. */ - gcov_read_unsigned (); - gcov_rewrite (); - gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); - gcov_write_unsigned (stamp); - if (ll_infos->pmu_tool_header) - gcov_write_tool_header (ll_infos->pmu_tool_header); - for (i = 0; i < ll_infos->ll_count; ++i) - { - /* Write each line. */ - gcov_write_ll_line (ll_infos->ll_array[i]); - } - gcov_truncate (); -} - -/* Write branch mispredict information INFO into the gcda file. The - gcda file has already been opened and is available for writing. */ - -static void -gcov_write_branch_mispredict_infos (void *info) -{ - unsigned i; - const brm_infos_t *brm_infos = (const brm_infos_t *)info; - gcov_unsigned_t stamp = 0; /* Don't use stamp as we don't support merge. */ - /* We don't support merge, and instead always rewrite the file. */ - gcov_rewrite (); - gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); - gcov_write_unsigned (stamp); - if (brm_infos->pmu_tool_header) - gcov_write_tool_header (brm_infos->pmu_tool_header); - for (i = 0; i < brm_infos->brm_count; ++i) - { - /* Write each line. */ - gcov_write_branch_mispredict_line (brm_infos->brm_array[i]); - } - gcov_truncate (); -} - /* Compute TOOL_HEADER length for writing into the gcov file. */ static gcov_unsigned_t @@ -1483,70 +229,4 @@ gcov_write_tool_header (gcov_pmu_tool_header_t *he gcov_write_string (header->full_header); } - -/* End PMU profiling. If GCDA_ERROR is non-zero then write profiling data into - already open gcda file */ - -void -__gcov_end_pmu_profiler (int gcda_error) -{ - int pid_status; - int wait_status; - pid_t pid; - pmu_tool_fns *tool_details; - - if (!the_pmu_tool_info) - return; - - tool_details = the_pmu_tool_info->tool_details; - pid = the_pmu_tool_info->pmu_tool_pid; - if (pid) - { - if (tool_debug) - fprintf (stderr, "terminating PMU profiling process %ld\n", (long)pid); - kill (pid, SIGTERM); - if (tool_debug) - fprintf (stderr, "parent: waiting for pmu process to end\n"); - wait_status = waitpid (pid, &pid_status, 0); - if (tool_debug) { - if (wait_status == pid) - fprintf (stderr, "Normal exit. Child terminated.\n"); - else - fprintf (stderr, "Abnormal exit. child status, %d.\n", pid_status); - } - } - - if (the_pmu_tool_info->pmu_profiling_state != PMU_OFF) - { - /* nothing to do */ - fprintf (stderr, - "__gcov_dump_pmu_profile: incorrect pmu state: %d, pid: %ld\n", - the_pmu_tool_info->pmu_profiling_state, - (unsigned long)pid); - return; - } - - if (!tool_details->parse_pmu_output) - return; - - /* Since we are going to parse the output, we also need symbolizer. */ - if (tool_details->start_symbolizer) - tool_details->start_symbolizer (getpid ()); - - if (!tool_details->parse_pmu_output - (the_pmu_tool_info->raw_pmu_profile_filename, - the_pmu_tool_info->pmu_data)) - { - if (!gcda_error && tool_details->gcov_write_pmu_data) - /* Write tool output into the gcda file. */ - tool_details->gcov_write_pmu_data (the_pmu_tool_info->pmu_data); - } - - if (tool_details->end_symbolizer) - tool_details->end_symbolizer (); - - if (tool_details->cleanup_pmu_data) - tool_details->cleanup_pmu_data (the_pmu_tool_info->pmu_data); -} - #endif Index: libgcc/libgcov.c =================================================================== --- libgcc/libgcov.c (revision 190135) +++ libgcc/libgcov.c (working copy) @@ -463,37 +463,6 @@ gcov_alloc_filename (void) gi_filename_up = gi_filename + prefix_length; } -/* Stop the pmu profiler and dump pmu profile info into the global file. */ - -static void -pmu_profile_stop (void) -{ - const char *pmu_profile_filename = __gcov_pmu_profile_filename; - const char *pmu_options = __gcov_pmu_profile_options; - size_t filename_length; - int gcda_error; - - if (!pmu_profile_filename || !pmu_options) - return; - - __gcov_stop_pmu_profiler (); - - filename_length = strlen (pmu_profile_filename); - if (filename_length > gcov_max_filename) - gcov_max_filename = filename_length; - /* Allocate and initialize the filename scratch space. */ - gcov_alloc_filename (); - GCOV_GET_FILENAME (prefix_length, gcov_prefix_strip, pmu_profile_filename, - gi_filename_up); - /* Open the gcda file for writing. We don't support merge yet. */ - gcda_error = gcov_open_by_filename (gi_filename); - __gcov_end_pmu_profiler (gcda_error); - if ((gcda_error = gcov_close ())) - gcov_error (gcda_error < 0 ? "pmu_profile_stop:%s:Overflow writing\n" : - "pmu_profile_stop:%s:Error writing\n", - gi_filename); -} - /* Sort N entries in VALUE_ARRAY in descending order. Each entry in VALUE_ARRAY has two values. The sorting is based on the second value. */ @@ -634,9 +603,6 @@ gcov_exit (void) if (gcov_dump_complete) return; - /* Stop and write the PMU profile data into the global file. */ - pmu_profile_stop (); - dump_module_info = gcov_exit_init (); for (gi_ptr = __gcov_list; gi_ptr; gi_ptr = gi_ptr->next) @@ -701,25 +667,11 @@ __gcov_init (struct gcov_info *info) { const char *ptr = info->filename; size_t filename_length = strlen (info->filename); - struct gcov_pmu_info pmu_info; /* Refresh the longest file name information. */ if (filename_length > gcov_max_filename) gcov_max_filename = filename_length; - /* Initialize the pmu profiler. */ - pmu_info.pmu_profile_filename = __gcov_pmu_profile_filename; - pmu_info.pmu_tool = __gcov_pmu_profile_options; - pmu_info.pmu_top_n_address = __gcov_pmu_top_n_address; - __gcov_init_pmu_profiler (&pmu_info); - if (pmu_info.pmu_profile_filename) - { - /* Refresh the longest file name information. */ - filename_length = strlen (pmu_info.pmu_profile_filename); - if (filename_length > gcov_max_filename) - gcov_max_filename = filename_length; - } - /* Assign the module ID (starting at 1). */ info->mod_info->ident = (++gcov_cur_module_id); gcc_assert (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (GEN_FUNC_GLOBAL_ID ( @@ -729,8 +681,6 @@ __gcov_init (struct gcov_info *info) if (!__gcov_list) { atexit (gcov_exit); - /* Start pmu profiler. */ - __gcov_start_pmu_profiler (); } info->next = __gcov_list; @@ -746,10 +696,8 @@ __gcov_init (struct gcov_info *info) void __gcov_flush (void) { - __gcov_stop_pmu_profiler (); gcov_exit (); gcov_clear (); - __gcov_start_pmu_profiler (); } #else /* __GCOV_KERNEL__ */