• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file opd_mapping.c
3  * Management of process mappings
4  *
5  * @remark Copyright 2002 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author John Levon
9  * @author Philippe Elie
10  */
11 
12 #include "opd_mapping.h"
13 #include "opd_proc.h"
14 #include "opd_image.h"
15 #include "opd_printf.h"
16 
17 #include "op_interface.h"
18 #include "op_config_24.h"
19 #include "op_libiberty.h"
20 
21 #include <sys/mman.h>
22 #include <limits.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 /* hash map device mmap */
28 static struct op_hash_index * hashmap;
29 /* already seen mapping name */
30 static char const * hash_name[OP_HASH_MAP_NR];
31 
32 
opd_cleanup_hash_name(void)33 void opd_cleanup_hash_name(void)
34 {
35 	int i;
36 	for (i = 0; i < OP_HASH_MAP_NR; ++i)
37 		free((char *)hash_name[i]);
38 
39 }
40 
41 
opd_init_hash_map(void)42 void opd_init_hash_map(void)
43 {
44 	extern fd_t hashmapdevfd;
45 
46 	hashmap = mmap(0, OP_HASH_MAP_SIZE, PROT_READ, MAP_SHARED, hashmapdevfd, 0);
47 	if ((long)hashmap == -1) {
48 		perror("oprofiled: couldn't mmap hash map");
49 		exit(EXIT_FAILURE);
50 	}
51 
52 }
53 
54 
opd_kill_maps(struct opd_proc * proc)55 void opd_kill_maps(struct opd_proc * proc)
56 {
57 	struct list_head * pos, * pos2;
58 
59 	list_for_each_safe(pos, pos2, &proc->maps) {
60 		struct opd_map * map = list_entry(pos, struct opd_map, next);
61 		list_del(pos);
62 		opd_delete_image(map->image);
63 		free(map);
64 	}
65 }
66 
67 
opd_add_mapping(struct opd_proc * proc,struct opd_image * image,unsigned long start,unsigned long offset,unsigned long end)68 void opd_add_mapping(struct opd_proc * proc, struct opd_image * image,
69 		unsigned long start, unsigned long offset, unsigned long end)
70 {
71 	struct opd_map * map;
72 
73 	verbprintf(vmisc, "Adding mapping for process %d: 0x%.8lx-0x%.8lx, off 0x%.8lx, \"%s\"\n",
74 		proc->tid, start, end, offset, image->name);
75 
76 	map = malloc(sizeof(struct opd_map));
77 
78 	/* first map is the primary image */
79 	if (list_empty(&proc->maps)) {
80 		if (proc->name)
81 			free((char *)proc->name);
82 		proc->name = xstrdup(image->name);
83 	}
84 
85 	image->ref_count++;
86 
87 	map->image = image;
88 	map->start = start;
89 	map->offset = offset;
90 	map->end = end;
91 	list_add_tail(&map->next, &proc->maps);
92 }
93 
94 
95 /**
96  * get_from_pool - retrieve string from hash map pool
97  * @param ind index into pool
98  */
get_from_pool(uint ind)99 inline static char * get_from_pool(uint ind)
100 {
101 	return ((char *)(hashmap + OP_HASH_MAP_NR) + ind);
102 }
103 
104 
105 /**
106  * opg_get_hash_name - find a mapping name from a hash
107  * @param hash hash value for this name
108  */
opd_get_hash_name(int hash)109 static char const * opd_get_hash_name(int hash)
110 {
111 	char file[PATH_MAX];
112 	char * c = &file[PATH_MAX-1];
113 	int orighash = hash;
114 
115 	if (hash_name[hash])
116 		return hash_name[hash];
117 
118 	*c = '\0';
119 	while (hash) {
120 		char * name = get_from_pool(hashmap[hash].name);
121 
122 		if (strlen(name) + 1 + strlen(c) >= PATH_MAX) {
123 			fprintf(stderr, "String \"%s\" too large.\n", c);
124 			exit(EXIT_FAILURE);
125 		}
126 
127 		c -= strlen(name) + 1;
128 		*c = '/';
129 		strncpy(c + 1, name, strlen(name));
130 
131 		/* move onto parent */
132 		hash = hashmap[hash].parent;
133 	}
134 
135 	return hash_name[orighash] = xstrdup(c);
136 }
137 
138 
opd_handle_mapping(struct op_note const * note)139 void opd_handle_mapping(struct op_note const * note)
140 {
141 	struct opd_proc * proc;
142 	struct opd_image * image;
143 	int hash;
144 	char const * name;
145 
146 	proc = opd_get_proc(note->pid, note->tgid);
147 
148 	if (!proc) {
149 		verbprintf(vmisc, "Told about mapping for non-existent process %u.\n", note->pid);
150 		proc = opd_new_proc(note->pid, note->tgid);
151 	}
152 
153 	hash = note->hash;
154 
155 	if (hash == -1) {
156 		/* possibly deleted file */
157 		return;
158 	}
159 
160 	if (hash < 0 || hash >= OP_HASH_MAP_NR) {
161 		fprintf(stderr, "hash value %u out of range.\n", hash);
162 		return;
163 	}
164 
165 	name = opd_get_hash_name(hash);
166 	image = opd_get_image(name, proc->name, 0, note->pid, note->tgid);
167 
168 	opd_add_mapping(proc, image, note->addr, note->offset,
169 	                note->addr + note->len);
170 }
171