operf_mangling.cpp

Go to the documentation of this file.
00001 /*
00002  * @file pe_profiling/operf_mangling.cpp
00003  * This file is based on daemon/opd_mangling and is used for
00004  * mangling and opening of sample files for operf.
00005  *
00006  * @remark Copyright 2011 OProfile authors
00007  * @remark Read the file COPYING
00008  *
00009  * Created on: Dec 15, 2011
00010  * @author Maynard Johnson
00011  * (C) Copyright IBM Corp. 2011
00012  */
00013 
00014 #include <sys/types.h>
00015 #include <iostream>
00016 
00017 #include "operf_utils.h"
00018 #include "operf_mangling.h"
00019 #include "operf_kernel.h"
00020 #include "operf_sfile.h"
00021 #include "operf_counter.h"
00022 #include "op_file.h"
00023 #include "op_sample_file.h"
00024 #include "op_mangle.h"
00025 #include "op_events.h"
00026 #include "op_libiberty.h"
00027 #include "cverb.h"
00028 
00029 #include <limits.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <errno.h>
00034 
00035 extern operf_read operfRead;
00036 extern op_cpu cpu_type;
00037 extern double cpu_speed;
00038 
00039 using namespace std;
00040 
00041 static const char * mangle_anon(struct operf_sfile const * anon)
00042 {
00043     char * name = (char *)xmalloc(PATH_MAX);
00044 
00045     snprintf(name, 1024, "%u.0x%llx.0x%llx", (unsigned int)anon->tgid,
00046            anon->start_addr, anon->end_addr);
00047 
00048     return (const char *)name;
00049 }
00050 
00051 static char *
00052 mangle_filename(struct operf_sfile * last, struct operf_sfile const * sf, int counter, int cg)
00053 {
00054     char * mangled;
00055     struct mangle_values values = {0, NULL, NULL, NULL, NULL, NULL, 0, 0, -1, -1, -1};
00056     const struct operf_event * event = operfRead.get_event_by_counter(counter);
00057 
00058     values.anon_name = NULL;
00059     values.flags = 0;
00060 
00061     if (sf->kernel) {
00062         values.image_name = sf->kernel->name;
00063         values.flags |= MANGLE_KERNEL;
00064     } else if (sf->is_anon) {
00065         values.flags |= MANGLE_ANON;
00066         values.image_name = mangle_anon(sf);
00067         values.anon_name = sf->image_name;
00068     } else {
00069         values.image_name = sf->image_name;
00070     }
00071     values.dep_name = sf->app_filename;
00072     if (operf_options::separate_thread) {
00073         values.flags |= MANGLE_TGID | MANGLE_TID;
00074         values.tid = sf->tid;
00075         values.tgid = sf->tgid;
00076     }
00077 
00078     if (operf_options::separate_cpu) {
00079         values.flags |= MANGLE_CPU;
00080         values.cpu = sf->cpu;
00081     }
00082 
00083     if (cg) {
00084         values.flags |= MANGLE_CALLGRAPH;
00085         if (last->kernel) {
00086             values.cg_image_name = last->kernel->name;
00087         } else if (last->is_anon) {
00088             values.flags |= MANGLE_CG_ANON;
00089             values.cg_image_name = mangle_anon((struct operf_sfile const *)last);
00090             values.anon_name = "anon";
00091         } else {
00092             values.cg_image_name = last->image_name;
00093         }
00094     }
00095 
00096     values.event_name = event->name;
00097     values.count = event->count;
00098     values.unit_mask = event->evt_um;
00099 
00100     mangled = op_mangle_filename(&values);
00101 
00102     if (values.flags & MANGLE_ANON)
00103         free((char *)values.image_name);
00104     if (values.flags & MANGLE_CG_ANON)
00105         free((char *)values.cg_image_name);
00106     return mangled;
00107 }
00108 
00109 static void fill_header(struct opd_header * header, unsigned long counter,
00110                         vma_t anon_start, vma_t cg_to_anon_start,
00111                         int is_kernel, int cg_to_is_kernel,
00112                         int spu_samples, uint64_t embed_offset, time_t mtime)
00113 {
00114     const operf_event_t * event = operfRead.get_event_by_counter(counter);
00115 
00116     memset(header, '\0', sizeof(struct opd_header));
00117     header->version = OPD_VERSION;
00118     memcpy(header->magic, OPD_MAGIC, sizeof(header->magic));
00119     header->cpu_type = cpu_type;
00120     header->ctr_event = event->op_evt_code;
00121     header->ctr_count = event->count;
00122     header->ctr_um = event->evt_um;
00123     header->is_kernel = is_kernel;
00124     header->cg_to_is_kernel = cg_to_is_kernel;
00125     header->cpu_speed = cpu_speed;
00126     header->mtime = mtime;
00127     header->anon_start = anon_start;
00128     header->spu_profile = spu_samples;
00129     header->embedded_offset = embed_offset;
00130     header->cg_to_anon_start = cg_to_anon_start;
00131 }
00132 
00133 int operf_open_sample_file(odb_t *file, struct operf_sfile *last,
00134                          struct operf_sfile * sf, int counter, int cg)
00135 {
00136     char * mangled;
00137     char const * binary;
00138     vma_t last_start = 0;
00139     int err;
00140 
00141     mangled = mangle_filename(last, sf, counter, cg);
00142 
00143     if (!mangled)
00144         return EINVAL;
00145 
00146     cverb << vsfile << "Opening \"" << mangled << "\"" << endl;
00147 
00148     create_path(mangled);
00149 
00150     /* locking sf will lock associated cg files too */
00151     operf_sfile_get(sf);
00152     if (sf != last)
00153         operf_sfile_get(last);
00154 
00155 retry:
00156     err = odb_open(file, mangled, ODB_RDWR, sizeof(struct opd_header));
00157 
00158     /* This should never happen unless someone is clearing out sample data dir. */
00159     if (err) {
00160         if (err == EMFILE) {
00161             if (operf_sfile_lru_clear()) {
00162                 cerr << "LRU cleared but odb_open() fails for " << mangled << endl;
00163                 abort();
00164             }
00165             goto retry;
00166         }
00167         if (err == EINTR) {
00168             cverb << vsfile << "operf: open of " << mangled << " was interrupted. Trying again." << endl;
00169             goto retry;
00170         }
00171 
00172         cerr << "operf: open of " << mangled << " failed: " << strerror(err) << endl;
00173         goto out;
00174     }
00175 
00176     if (!sf->kernel)
00177         binary = sf->image_name;
00178     else
00179         binary = sf->kernel->name;
00180 
00181     if (last && last->is_anon)
00182         last_start = last->start_addr;
00183 
00184     fill_header((struct opd_header *)odb_get_data(file), counter,
00185             sf->is_anon ? sf->start_addr : 0, last_start,
00186             !!sf->kernel, last ? !!last->kernel : 0,
00187             0, 0,
00188             binary ? op_get_mtime(binary) : 0);
00189 
00190 out:
00191     operf_sfile_put(sf);
00192     if (sf != last)
00193         operf_sfile_put(last);
00194     free(mangled);
00195     return err;
00196 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1