blob: 699c475f6e09154b89242659f29d2bab4c12bb4d [file] [log] [blame]
Upstreamcc2ee171970-01-12 13:46:40 +00001/**
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 */
28static struct op_hash_index * hashmap;
29/* already seen mapping name */
30static char const * hash_name[OP_HASH_MAP_NR];
31
32
33void 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
42void 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
55void 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
68void 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 */
99inline 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 */
109static 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
139void 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}