| /** |
| * @file daemon/opd_mangling.c |
| * Mangling and opening of sample files |
| * |
| * @remark Copyright 2002 OProfile authors |
| * @remark Read the file COPYING |
| * |
| * @author John Levon |
| * @author Philippe Elie |
| */ |
| |
| #include <sys/types.h> |
| |
| #include "opd_mangling.h" |
| #include "opd_kernel.h" |
| #include "opd_cookie.h" |
| #include "opd_sfile.h" |
| #include "opd_anon.h" |
| #include "opd_printf.h" |
| #include "opd_events.h" |
| #include "oprofiled.h" |
| |
| #include "op_file.h" |
| #include "op_sample_file.h" |
| #include "op_config.h" |
| #include "op_mangle.h" |
| #include "op_events.h" |
| #include "op_libiberty.h" |
| |
| #include <limits.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| |
| static char const * get_dep_name(struct sfile const * sf) |
| { |
| if (sf->anon) |
| return find_cookie(sf->app_cookie); |
| |
| /* avoid to call find_cookie(), caller can recover using image_name */ |
| if (sf->cookie == sf->app_cookie) |
| return NULL; |
| |
| if (!separate_kernel && !(separate_lib && !sf->kernel)) |
| return NULL; |
| |
| /* this will fail if e.g. kernel thread */ |
| if (sf->app_cookie == 0) |
| return NULL; |
| |
| return find_cookie(sf->app_cookie); |
| } |
| |
| |
| static char * mangle_anon(struct anon_mapping const * anon) |
| { |
| char * name = xmalloc(PATH_MAX); |
| |
| snprintf(name, 1024, "%u.0x%llx.0x%llx", (unsigned int)anon->tgid, |
| anon->start, anon->end); |
| |
| return name; |
| } |
| |
| |
| static char * |
| mangle_filename(struct sfile * last, struct sfile const * sf, int counter, int cg) |
| { |
| char * mangled; |
| struct mangle_values values; |
| struct opd_event * event = find_counter_event(counter); |
| |
| values.flags = 0; |
| |
| if (sf->kernel) { |
| values.image_name = sf->kernel->name; |
| values.flags |= MANGLE_KERNEL; |
| } else if (sf->anon) { |
| values.flags |= MANGLE_ANON; |
| values.image_name = mangle_anon(sf->anon); |
| values.anon_name = sf->anon->name; |
| } else { |
| values.image_name = find_cookie(sf->cookie); |
| } |
| |
| values.dep_name = get_dep_name(sf); |
| if (!values.dep_name) |
| values.dep_name = values.image_name; |
| |
| /* FIXME: log */ |
| if (!values.image_name || !values.dep_name) |
| return NULL; |
| |
| if (separate_thread) { |
| values.flags |= MANGLE_TGID | MANGLE_TID; |
| values.tid = sf->tid; |
| values.tgid = sf->tgid; |
| } |
| |
| if (separate_cpu) { |
| values.flags |= MANGLE_CPU; |
| values.cpu = sf->cpu; |
| } |
| |
| if (cg) { |
| values.flags |= MANGLE_CALLGRAPH; |
| if (last->kernel) { |
| values.cg_image_name = last->kernel->name; |
| } else if (last->anon) { |
| values.flags |= MANGLE_CG_ANON; |
| values.cg_image_name = mangle_anon(last->anon); |
| values.anon_name = last->anon->name; |
| } else { |
| values.cg_image_name = find_cookie(last->cookie); |
| } |
| |
| /* FIXME: log */ |
| if (!values.cg_image_name) { |
| if (values.flags & MANGLE_ANON) |
| free((char *)values.image_name); |
| return NULL; |
| } |
| } |
| |
| values.event_name = event->name; |
| values.count = event->count; |
| values.unit_mask = event->um; |
| |
| mangled = op_mangle_filename(&values); |
| |
| if (values.flags & MANGLE_ANON) |
| free((char *)values.image_name); |
| if (values.flags & MANGLE_CG_ANON) |
| free((char *)values.cg_image_name); |
| return mangled; |
| } |
| |
| |
| int opd_open_sample_file(odb_t *file, struct sfile *last, |
| struct sfile * sf, int counter, int cg) |
| { |
| char * mangled; |
| char const * binary; |
| int spu_profile = 0; |
| vma_t last_start = 0; |
| int err; |
| |
| mangled = mangle_filename(last, sf, counter, cg); |
| |
| if (!mangled) |
| return EINVAL; |
| |
| verbprintf(vsfile, "Opening \"%s\"\n", mangled); |
| |
| create_path(mangled); |
| |
| /* locking sf will lock associated cg files too */ |
| sfile_get(sf); |
| if (sf != last) |
| sfile_get(last); |
| |
| retry: |
| err = odb_open(file, mangled, ODB_RDWR, sizeof(struct opd_header)); |
| |
| /* This can naturally happen when racing against opcontrol --reset. */ |
| if (err) { |
| if (err == EMFILE) { |
| if (sfile_lru_clear()) { |
| printf("LRU cleared but odb_open() fails for %s.\n", mangled); |
| abort(); |
| } |
| goto retry; |
| } |
| |
| fprintf(stderr, "oprofiled: open of %s failed: %s\n", |
| mangled, strerror(err)); |
| goto out; |
| } |
| |
| if (!sf->kernel) |
| binary = find_cookie(sf->cookie); |
| else |
| binary = sf->kernel->name; |
| |
| if (last && last->anon) |
| last_start = last->anon->start; |
| |
| if (sf->embedded_offset != UNUSED_EMBEDDED_OFFSET) |
| spu_profile = 1; |
| |
| fill_header(odb_get_data(file), counter, |
| sf->anon ? sf->anon->start : 0, last_start, |
| !!sf->kernel, last ? !!last->kernel : 0, |
| spu_profile, sf->embedded_offset, |
| binary ? op_get_mtime(binary) : 0); |
| |
| out: |
| sfile_put(sf); |
| if (sf != last) |
| sfile_put(last); |
| free(mangled); |
| return err; |
| } |