00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
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
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 }