opd_mapping.c
Go to the documentation of this file.00001
00012 #include "opd_mapping.h"
00013 #include "opd_proc.h"
00014 #include "opd_image.h"
00015 #include "opd_printf.h"
00016
00017 #include "op_interface.h"
00018 #include "op_config_24.h"
00019 #include "op_libiberty.h"
00020
00021 #include <sys/mman.h>
00022 #include <limits.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026
00027
00028 static struct op_hash_index * hashmap;
00029
00030 static char const * hash_name[OP_HASH_MAP_NR];
00031
00032
00033 void opd_cleanup_hash_name(void)
00034 {
00035 int i;
00036 for (i = 0; i < OP_HASH_MAP_NR; ++i)
00037 free((char *)hash_name[i]);
00038
00039 }
00040
00041
00042 void opd_init_hash_map(void)
00043 {
00044 extern fd_t hashmapdevfd;
00045
00046 hashmap = mmap(0, OP_HASH_MAP_SIZE, PROT_READ, MAP_SHARED, hashmapdevfd, 0);
00047 if ((long)hashmap == -1) {
00048 perror("oprofiled: couldn't mmap hash map");
00049 exit(EXIT_FAILURE);
00050 }
00051
00052 }
00053
00054
00055 void opd_kill_maps(struct opd_proc * proc)
00056 {
00057 struct list_head * pos, * pos2;
00058
00059 list_for_each_safe(pos, pos2, &proc->maps) {
00060 struct opd_map * map = list_entry(pos, struct opd_map, next);
00061 list_del(pos);
00062 opd_delete_image(map->image);
00063 free(map);
00064 }
00065 }
00066
00067
00068 void opd_add_mapping(struct opd_proc * proc, struct opd_image * image,
00069 unsigned long start, unsigned long offset, unsigned long end)
00070 {
00071 struct opd_map * map;
00072
00073 verbprintf(vmisc, "Adding mapping for process %d: 0x%.8lx-0x%.8lx, off 0x%.8lx, \"%s\"\n",
00074 proc->tid, start, end, offset, image->name);
00075
00076 map = malloc(sizeof(struct opd_map));
00077
00078
00079 if (list_empty(&proc->maps)) {
00080 if (proc->name)
00081 free((char *)proc->name);
00082 proc->name = xstrdup(image->name);
00083 }
00084
00085 image->ref_count++;
00086
00087 map->image = image;
00088 map->start = start;
00089 map->offset = offset;
00090 map->end = end;
00091 list_add_tail(&map->next, &proc->maps);
00092 }
00093
00094
00099 inline static char * get_from_pool(uint ind)
00100 {
00101 return ((char *)(hashmap + OP_HASH_MAP_NR) + ind);
00102 }
00103
00104
00109 static char const * opd_get_hash_name(int hash)
00110 {
00111 char file[PATH_MAX];
00112 char * c = &file[PATH_MAX-1];
00113 int orighash = hash;
00114
00115 if (hash_name[hash])
00116 return hash_name[hash];
00117
00118 *c = '\0';
00119 while (hash) {
00120 char * name = get_from_pool(hashmap[hash].name);
00121
00122 if (strlen(name) + 1 + strlen(c) >= PATH_MAX) {
00123 fprintf(stderr, "String \"%s\" too large.\n", c);
00124 exit(EXIT_FAILURE);
00125 }
00126
00127 c -= strlen(name) + 1;
00128 *c = '/';
00129 strncpy(c + 1, name, strlen(name));
00130
00131
00132 hash = hashmap[hash].parent;
00133 }
00134
00135 return hash_name[orighash] = xstrdup(c);
00136 }
00137
00138
00139 void opd_handle_mapping(struct op_note const * note)
00140 {
00141 struct opd_proc * proc;
00142 struct opd_image * image;
00143 int hash;
00144 char const * name;
00145
00146 proc = opd_get_proc(note->pid, note->tgid);
00147
00148 if (!proc) {
00149 verbprintf(vmisc, "Told about mapping for non-existent process %u.\n", note->pid);
00150 proc = opd_new_proc(note->pid, note->tgid);
00151 }
00152
00153 hash = note->hash;
00154
00155 if (hash == -1) {
00156
00157 return;
00158 }
00159
00160 if (hash < 0 || hash >= OP_HASH_MAP_NR) {
00161 fprintf(stderr, "hash value %u out of range.\n", hash);
00162 return;
00163 }
00164
00165 name = opd_get_hash_name(hash);
00166 image = opd_get_image(name, proc->name, 0, note->pid, note->tgid);
00167
00168 opd_add_mapping(proc, image, note->addr, note->offset,
00169 note->addr + note->len);
00170 }