[a8d9ee]: / daemon / liblegacy / opd_mapping.c  Maximize  Restore  History

Download this file

171 lines (130 with data), 3.5 kB

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