Linux 2.6.31.8
[linux/fpc-iii.git] / tools / perf / util / module.c
blob702083d342ff7726e95ea83abd8958e46f8de603
1 #include "util.h"
2 #include "../perf.h"
3 #include "string.h"
4 #include "module.h"
6 #include <libelf.h>
7 #include <gelf.h>
8 #include <elf.h>
9 #include <dirent.h>
10 #include <sys/utsname.h>
12 static unsigned int crc32(const char *p, unsigned int len)
14 int i;
15 unsigned int crc = 0;
17 while (len--) {
18 crc ^= *p++;
19 for (i = 0; i < 8; i++)
20 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
22 return crc;
25 /* module section methods */
27 struct sec_dso *sec_dso__new_dso(const char *name)
29 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
31 if (self != NULL) {
32 strcpy(self->name, name);
33 self->secs = RB_ROOT;
34 self->find_section = sec_dso__find_section;
37 return self;
40 static void sec_dso__delete_section(struct section *self)
42 free(((void *)self));
45 void sec_dso__delete_sections(struct sec_dso *self)
47 struct section *pos;
48 struct rb_node *next = rb_first(&self->secs);
50 while (next) {
51 pos = rb_entry(next, struct section, rb_node);
52 next = rb_next(&pos->rb_node);
53 rb_erase(&pos->rb_node, &self->secs);
54 sec_dso__delete_section(pos);
58 void sec_dso__delete_self(struct sec_dso *self)
60 sec_dso__delete_sections(self);
61 free(self);
64 static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
66 struct rb_node **p = &self->secs.rb_node;
67 struct rb_node *parent = NULL;
68 const u64 hash = sec->hash;
69 struct section *s;
71 while (*p != NULL) {
72 parent = *p;
73 s = rb_entry(parent, struct section, rb_node);
74 if (hash < s->hash)
75 p = &(*p)->rb_left;
76 else
77 p = &(*p)->rb_right;
79 rb_link_node(&sec->rb_node, parent, p);
80 rb_insert_color(&sec->rb_node, &self->secs);
83 struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
85 struct rb_node *n;
86 u64 hash;
87 int len;
89 if (self == NULL)
90 return NULL;
92 len = strlen(name);
93 hash = crc32(name, len);
95 n = self->secs.rb_node;
97 while (n) {
98 struct section *s = rb_entry(n, struct section, rb_node);
100 if (hash < s->hash)
101 n = n->rb_left;
102 else if (hash > s->hash)
103 n = n->rb_right;
104 else {
105 if (!strcmp(name, s->name))
106 return s;
107 else
108 n = rb_next(&s->rb_node);
112 return NULL;
115 static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
117 return fprintf(fp, "name:%s vma:%llx path:%s\n",
118 self->name, self->vma, self->path);
121 size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
123 size_t ret = fprintf(fp, "dso: %s\n", self->name);
125 struct rb_node *nd;
126 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
127 struct section *pos = rb_entry(nd, struct section, rb_node);
128 ret += sec_dso__fprintf_section(pos, fp);
131 return ret;
134 static struct section *section__new(const char *name, const char *path)
136 struct section *self = calloc(1, sizeof(*self));
138 if (!self)
139 goto out_failure;
141 self->name = calloc(1, strlen(name) + 1);
142 if (!self->name)
143 goto out_failure;
145 self->path = calloc(1, strlen(path) + 1);
146 if (!self->path)
147 goto out_failure;
149 strcpy(self->name, name);
150 strcpy(self->path, path);
151 self->hash = crc32(self->name, strlen(name));
153 return self;
155 out_failure:
156 if (self) {
157 if (self->name)
158 free(self->name);
159 if (self->path)
160 free(self->path);
161 free(self);
164 return NULL;
167 /* module methods */
169 struct mod_dso *mod_dso__new_dso(const char *name)
171 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
173 if (self != NULL) {
174 strcpy(self->name, name);
175 self->mods = RB_ROOT;
176 self->find_module = mod_dso__find_module;
179 return self;
182 static void mod_dso__delete_module(struct module *self)
184 free(((void *)self));
187 void mod_dso__delete_modules(struct mod_dso *self)
189 struct module *pos;
190 struct rb_node *next = rb_first(&self->mods);
192 while (next) {
193 pos = rb_entry(next, struct module, rb_node);
194 next = rb_next(&pos->rb_node);
195 rb_erase(&pos->rb_node, &self->mods);
196 mod_dso__delete_module(pos);
200 void mod_dso__delete_self(struct mod_dso *self)
202 mod_dso__delete_modules(self);
203 free(self);
206 static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
208 struct rb_node **p = &self->mods.rb_node;
209 struct rb_node *parent = NULL;
210 const u64 hash = mod->hash;
211 struct module *m;
213 while (*p != NULL) {
214 parent = *p;
215 m = rb_entry(parent, struct module, rb_node);
216 if (hash < m->hash)
217 p = &(*p)->rb_left;
218 else
219 p = &(*p)->rb_right;
221 rb_link_node(&mod->rb_node, parent, p);
222 rb_insert_color(&mod->rb_node, &self->mods);
225 struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
227 struct rb_node *n;
228 u64 hash;
229 int len;
231 if (self == NULL)
232 return NULL;
234 len = strlen(name);
235 hash = crc32(name, len);
237 n = self->mods.rb_node;
239 while (n) {
240 struct module *m = rb_entry(n, struct module, rb_node);
242 if (hash < m->hash)
243 n = n->rb_left;
244 else if (hash > m->hash)
245 n = n->rb_right;
246 else {
247 if (!strcmp(name, m->name))
248 return m;
249 else
250 n = rb_next(&m->rb_node);
254 return NULL;
257 static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
259 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
262 size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
264 struct rb_node *nd;
265 size_t ret;
267 ret = fprintf(fp, "dso: %s\n", self->name);
269 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
270 struct module *pos = rb_entry(nd, struct module, rb_node);
272 ret += mod_dso__fprintf_module(pos, fp);
275 return ret;
278 static struct module *module__new(const char *name, const char *path)
280 struct module *self = calloc(1, sizeof(*self));
282 if (!self)
283 goto out_failure;
285 self->name = calloc(1, strlen(name) + 1);
286 if (!self->name)
287 goto out_failure;
289 self->path = calloc(1, strlen(path) + 1);
290 if (!self->path)
291 goto out_failure;
293 strcpy(self->name, name);
294 strcpy(self->path, path);
295 self->hash = crc32(self->name, strlen(name));
297 return self;
299 out_failure:
300 if (self) {
301 if (self->name)
302 free(self->name);
303 if (self->path)
304 free(self->path);
305 free(self);
308 return NULL;
311 static int mod_dso__load_sections(struct module *mod)
313 int count = 0, path_len;
314 struct dirent *entry;
315 char *line = NULL;
316 char *dir_path;
317 DIR *dir;
318 size_t n;
320 path_len = strlen("/sys/module/");
321 path_len += strlen(mod->name);
322 path_len += strlen("/sections/");
324 dir_path = calloc(1, path_len + 1);
325 if (dir_path == NULL)
326 goto out_failure;
328 strcat(dir_path, "/sys/module/");
329 strcat(dir_path, mod->name);
330 strcat(dir_path, "/sections/");
332 dir = opendir(dir_path);
333 if (dir == NULL)
334 goto out_free;
336 while ((entry = readdir(dir))) {
337 struct section *section;
338 char *path, *vma;
339 int line_len;
340 FILE *file;
342 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
343 continue;
345 path = calloc(1, path_len + strlen(entry->d_name) + 1);
346 if (path == NULL)
347 break;
348 strcat(path, dir_path);
349 strcat(path, entry->d_name);
351 file = fopen(path, "r");
352 if (file == NULL) {
353 free(path);
354 break;
357 line_len = getline(&line, &n, file);
358 if (line_len < 0) {
359 free(path);
360 fclose(file);
361 break;
364 if (!line) {
365 free(path);
366 fclose(file);
367 break;
370 line[--line_len] = '\0'; /* \n */
372 vma = strstr(line, "0x");
373 if (!vma) {
374 free(path);
375 fclose(file);
376 break;
378 vma += 2;
380 section = section__new(entry->d_name, path);
381 if (!section) {
382 fprintf(stderr, "load_sections: allocation error\n");
383 free(path);
384 fclose(file);
385 break;
388 hex2u64(vma, &section->vma);
389 sec_dso__insert_section(mod->sections, section);
391 free(path);
392 fclose(file);
393 count++;
396 closedir(dir);
397 free(line);
398 free(dir_path);
400 return count;
402 out_free:
403 free(dir_path);
405 out_failure:
406 return count;
409 static int mod_dso__load_module_paths(struct mod_dso *self)
411 struct utsname uts;
412 int count = 0, len;
413 char *line = NULL;
414 FILE *file;
415 char *path;
416 size_t n;
418 if (uname(&uts) < 0)
419 goto out_failure;
421 len = strlen("/lib/modules/");
422 len += strlen(uts.release);
423 len += strlen("/modules.dep");
425 path = calloc(1, len + 1);
426 if (path == NULL)
427 goto out_failure;
429 strcat(path, "/lib/modules/");
430 strcat(path, uts.release);
431 strcat(path, "/modules.dep");
433 file = fopen(path, "r");
434 free(path);
435 if (file == NULL)
436 goto out_failure;
438 while (!feof(file)) {
439 char *path, *name, *tmp;
440 struct module *module;
441 int line_len, len;
443 line_len = getline(&line, &n, file);
444 if (line_len < 0)
445 break;
447 if (!line)
448 goto out_failure;
450 line[--line_len] = '\0'; /* \n */
452 path = strtok(line, ":");
453 if (!path)
454 goto out_failure;
456 name = strdup(path);
457 name = strtok(name, "/");
459 tmp = name;
461 while (tmp) {
462 tmp = strtok(NULL, "/");
463 if (tmp)
464 name = tmp;
466 name = strsep(&name, ".");
468 /* Quirk: replace '-' with '_' in sound modules */
469 for (len = strlen(name); len; len--) {
470 if (*(name+len) == '-')
471 *(name+len) = '_';
474 module = module__new(name, path);
475 if (!module) {
476 fprintf(stderr, "load_module_paths: allocation error\n");
477 goto out_failure;
479 mod_dso__insert_module(self, module);
481 module->sections = sec_dso__new_dso("sections");
482 if (!module->sections) {
483 fprintf(stderr, "load_module_paths: allocation error\n");
484 goto out_failure;
487 module->active = mod_dso__load_sections(module);
489 if (module->active > 0)
490 count++;
493 free(line);
494 fclose(file);
496 return count;
498 out_failure:
499 return -1;
502 int mod_dso__load_modules(struct mod_dso *dso)
504 int err;
506 err = mod_dso__load_module_paths(dso);
508 return err;