diff options
Diffstat (limited to 'tools/perf/util/module.c')
-rw-r--r-- | tools/perf/util/module.c | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c deleted file mode 100644 index 0d8c85defcd2..000000000000 --- a/tools/perf/util/module.c +++ /dev/null | |||
@@ -1,545 +0,0 @@ | |||
1 | #include "util.h" | ||
2 | #include "../perf.h" | ||
3 | #include "string.h" | ||
4 | #include "module.h" | ||
5 | |||
6 | #include <libelf.h> | ||
7 | #include <libgen.h> | ||
8 | #include <gelf.h> | ||
9 | #include <elf.h> | ||
10 | #include <dirent.h> | ||
11 | #include <sys/utsname.h> | ||
12 | |||
13 | static unsigned int crc32(const char *p, unsigned int len) | ||
14 | { | ||
15 | int i; | ||
16 | unsigned int crc = 0; | ||
17 | |||
18 | while (len--) { | ||
19 | crc ^= *p++; | ||
20 | for (i = 0; i < 8; i++) | ||
21 | crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); | ||
22 | } | ||
23 | return crc; | ||
24 | } | ||
25 | |||
26 | /* module section methods */ | ||
27 | |||
28 | struct sec_dso *sec_dso__new_dso(const char *name) | ||
29 | { | ||
30 | struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1); | ||
31 | |||
32 | if (self != NULL) { | ||
33 | strcpy(self->name, name); | ||
34 | self->secs = RB_ROOT; | ||
35 | self->find_section = sec_dso__find_section; | ||
36 | } | ||
37 | |||
38 | return self; | ||
39 | } | ||
40 | |||
41 | static void sec_dso__delete_section(struct section *self) | ||
42 | { | ||
43 | free(((void *)self)); | ||
44 | } | ||
45 | |||
46 | void sec_dso__delete_sections(struct sec_dso *self) | ||
47 | { | ||
48 | struct section *pos; | ||
49 | struct rb_node *next = rb_first(&self->secs); | ||
50 | |||
51 | while (next) { | ||
52 | pos = rb_entry(next, struct section, rb_node); | ||
53 | next = rb_next(&pos->rb_node); | ||
54 | rb_erase(&pos->rb_node, &self->secs); | ||
55 | sec_dso__delete_section(pos); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | void sec_dso__delete_self(struct sec_dso *self) | ||
60 | { | ||
61 | sec_dso__delete_sections(self); | ||
62 | free(self); | ||
63 | } | ||
64 | |||
65 | static void sec_dso__insert_section(struct sec_dso *self, struct section *sec) | ||
66 | { | ||
67 | struct rb_node **p = &self->secs.rb_node; | ||
68 | struct rb_node *parent = NULL; | ||
69 | const u64 hash = sec->hash; | ||
70 | struct section *s; | ||
71 | |||
72 | while (*p != NULL) { | ||
73 | parent = *p; | ||
74 | s = rb_entry(parent, struct section, rb_node); | ||
75 | if (hash < s->hash) | ||
76 | p = &(*p)->rb_left; | ||
77 | else | ||
78 | p = &(*p)->rb_right; | ||
79 | } | ||
80 | rb_link_node(&sec->rb_node, parent, p); | ||
81 | rb_insert_color(&sec->rb_node, &self->secs); | ||
82 | } | ||
83 | |||
84 | struct section *sec_dso__find_section(struct sec_dso *self, const char *name) | ||
85 | { | ||
86 | struct rb_node *n; | ||
87 | u64 hash; | ||
88 | int len; | ||
89 | |||
90 | if (self == NULL) | ||
91 | return NULL; | ||
92 | |||
93 | len = strlen(name); | ||
94 | hash = crc32(name, len); | ||
95 | |||
96 | n = self->secs.rb_node; | ||
97 | |||
98 | while (n) { | ||
99 | struct section *s = rb_entry(n, struct section, rb_node); | ||
100 | |||
101 | if (hash < s->hash) | ||
102 | n = n->rb_left; | ||
103 | else if (hash > s->hash) | ||
104 | n = n->rb_right; | ||
105 | else { | ||
106 | if (!strcmp(name, s->name)) | ||
107 | return s; | ||
108 | else | ||
109 | n = rb_next(&s->rb_node); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | return NULL; | ||
114 | } | ||
115 | |||
116 | static size_t sec_dso__fprintf_section(struct section *self, FILE *fp) | ||
117 | { | ||
118 | return fprintf(fp, "name:%s vma:%llx path:%s\n", | ||
119 | self->name, self->vma, self->path); | ||
120 | } | ||
121 | |||
122 | size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp) | ||
123 | { | ||
124 | size_t ret = fprintf(fp, "dso: %s\n", self->name); | ||
125 | |||
126 | struct rb_node *nd; | ||
127 | for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) { | ||
128 | struct section *pos = rb_entry(nd, struct section, rb_node); | ||
129 | ret += sec_dso__fprintf_section(pos, fp); | ||
130 | } | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static struct section *section__new(const char *name, const char *path) | ||
136 | { | ||
137 | struct section *self = calloc(1, sizeof(*self)); | ||
138 | |||
139 | if (!self) | ||
140 | goto out_failure; | ||
141 | |||
142 | self->name = calloc(1, strlen(name) + 1); | ||
143 | if (!self->name) | ||
144 | goto out_failure; | ||
145 | |||
146 | self->path = calloc(1, strlen(path) + 1); | ||
147 | if (!self->path) | ||
148 | goto out_failure; | ||
149 | |||
150 | strcpy(self->name, name); | ||
151 | strcpy(self->path, path); | ||
152 | self->hash = crc32(self->name, strlen(name)); | ||
153 | |||
154 | return self; | ||
155 | |||
156 | out_failure: | ||
157 | if (self) { | ||
158 | if (self->name) | ||
159 | free(self->name); | ||
160 | if (self->path) | ||
161 | free(self->path); | ||
162 | free(self); | ||
163 | } | ||
164 | |||
165 | return NULL; | ||
166 | } | ||
167 | |||
168 | /* module methods */ | ||
169 | |||
170 | struct mod_dso *mod_dso__new_dso(const char *name) | ||
171 | { | ||
172 | struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1); | ||
173 | |||
174 | if (self != NULL) { | ||
175 | strcpy(self->name, name); | ||
176 | self->mods = RB_ROOT; | ||
177 | self->find_module = mod_dso__find_module; | ||
178 | } | ||
179 | |||
180 | return self; | ||
181 | } | ||
182 | |||
183 | static void mod_dso__delete_module(struct module *self) | ||
184 | { | ||
185 | free(((void *)self)); | ||
186 | } | ||
187 | |||
188 | void mod_dso__delete_modules(struct mod_dso *self) | ||
189 | { | ||
190 | struct module *pos; | ||
191 | struct rb_node *next = rb_first(&self->mods); | ||
192 | |||
193 | while (next) { | ||
194 | pos = rb_entry(next, struct module, rb_node); | ||
195 | next = rb_next(&pos->rb_node); | ||
196 | rb_erase(&pos->rb_node, &self->mods); | ||
197 | mod_dso__delete_module(pos); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | void mod_dso__delete_self(struct mod_dso *self) | ||
202 | { | ||
203 | mod_dso__delete_modules(self); | ||
204 | free(self); | ||
205 | } | ||
206 | |||
207 | static void mod_dso__insert_module(struct mod_dso *self, struct module *mod) | ||
208 | { | ||
209 | struct rb_node **p = &self->mods.rb_node; | ||
210 | struct rb_node *parent = NULL; | ||
211 | const u64 hash = mod->hash; | ||
212 | struct module *m; | ||
213 | |||
214 | while (*p != NULL) { | ||
215 | parent = *p; | ||
216 | m = rb_entry(parent, struct module, rb_node); | ||
217 | if (hash < m->hash) | ||
218 | p = &(*p)->rb_left; | ||
219 | else | ||
220 | p = &(*p)->rb_right; | ||
221 | } | ||
222 | rb_link_node(&mod->rb_node, parent, p); | ||
223 | rb_insert_color(&mod->rb_node, &self->mods); | ||
224 | } | ||
225 | |||
226 | struct module *mod_dso__find_module(struct mod_dso *self, const char *name) | ||
227 | { | ||
228 | struct rb_node *n; | ||
229 | u64 hash; | ||
230 | int len; | ||
231 | |||
232 | if (self == NULL) | ||
233 | return NULL; | ||
234 | |||
235 | len = strlen(name); | ||
236 | hash = crc32(name, len); | ||
237 | |||
238 | n = self->mods.rb_node; | ||
239 | |||
240 | while (n) { | ||
241 | struct module *m = rb_entry(n, struct module, rb_node); | ||
242 | |||
243 | if (hash < m->hash) | ||
244 | n = n->rb_left; | ||
245 | else if (hash > m->hash) | ||
246 | n = n->rb_right; | ||
247 | else { | ||
248 | if (!strcmp(name, m->name)) | ||
249 | return m; | ||
250 | else | ||
251 | n = rb_next(&m->rb_node); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | return NULL; | ||
256 | } | ||
257 | |||
258 | static size_t mod_dso__fprintf_module(struct module *self, FILE *fp) | ||
259 | { | ||
260 | return fprintf(fp, "name:%s path:%s\n", self->name, self->path); | ||
261 | } | ||
262 | |||
263 | size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp) | ||
264 | { | ||
265 | struct rb_node *nd; | ||
266 | size_t ret; | ||
267 | |||
268 | ret = fprintf(fp, "dso: %s\n", self->name); | ||
269 | |||
270 | for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) { | ||
271 | struct module *pos = rb_entry(nd, struct module, rb_node); | ||
272 | |||
273 | ret += mod_dso__fprintf_module(pos, fp); | ||
274 | } | ||
275 | |||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | static struct module *module__new(const char *name, const char *path) | ||
280 | { | ||
281 | struct module *self = calloc(1, sizeof(*self)); | ||
282 | |||
283 | if (!self) | ||
284 | goto out_failure; | ||
285 | |||
286 | self->name = calloc(1, strlen(name) + 1); | ||
287 | if (!self->name) | ||
288 | goto out_failure; | ||
289 | |||
290 | self->path = calloc(1, strlen(path) + 1); | ||
291 | if (!self->path) | ||
292 | goto out_failure; | ||
293 | |||
294 | strcpy(self->name, name); | ||
295 | strcpy(self->path, path); | ||
296 | self->hash = crc32(self->name, strlen(name)); | ||
297 | |||
298 | return self; | ||
299 | |||
300 | out_failure: | ||
301 | if (self) { | ||
302 | if (self->name) | ||
303 | free(self->name); | ||
304 | if (self->path) | ||
305 | free(self->path); | ||
306 | free(self); | ||
307 | } | ||
308 | |||
309 | return NULL; | ||
310 | } | ||
311 | |||
312 | static int mod_dso__load_sections(struct module *mod) | ||
313 | { | ||
314 | int count = 0, path_len; | ||
315 | struct dirent *entry; | ||
316 | char *line = NULL; | ||
317 | char *dir_path; | ||
318 | DIR *dir; | ||
319 | size_t n; | ||
320 | |||
321 | path_len = strlen("/sys/module/"); | ||
322 | path_len += strlen(mod->name); | ||
323 | path_len += strlen("/sections/"); | ||
324 | |||
325 | dir_path = calloc(1, path_len + 1); | ||
326 | if (dir_path == NULL) | ||
327 | goto out_failure; | ||
328 | |||
329 | strcat(dir_path, "/sys/module/"); | ||
330 | strcat(dir_path, mod->name); | ||
331 | strcat(dir_path, "/sections/"); | ||
332 | |||
333 | dir = opendir(dir_path); | ||
334 | if (dir == NULL) | ||
335 | goto out_free; | ||
336 | |||
337 | while ((entry = readdir(dir))) { | ||
338 | struct section *section; | ||
339 | char *path, *vma; | ||
340 | int line_len; | ||
341 | FILE *file; | ||
342 | |||
343 | if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) | ||
344 | continue; | ||
345 | |||
346 | path = calloc(1, path_len + strlen(entry->d_name) + 1); | ||
347 | if (path == NULL) | ||
348 | break; | ||
349 | strcat(path, dir_path); | ||
350 | strcat(path, entry->d_name); | ||
351 | |||
352 | file = fopen(path, "r"); | ||
353 | if (file == NULL) { | ||
354 | free(path); | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | line_len = getline(&line, &n, file); | ||
359 | if (line_len < 0) { | ||
360 | free(path); | ||
361 | fclose(file); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | if (!line) { | ||
366 | free(path); | ||
367 | fclose(file); | ||
368 | break; | ||
369 | } | ||
370 | |||
371 | line[--line_len] = '\0'; /* \n */ | ||
372 | |||
373 | vma = strstr(line, "0x"); | ||
374 | if (!vma) { | ||
375 | free(path); | ||
376 | fclose(file); | ||
377 | break; | ||
378 | } | ||
379 | vma += 2; | ||
380 | |||
381 | section = section__new(entry->d_name, path); | ||
382 | if (!section) { | ||
383 | fprintf(stderr, "load_sections: allocation error\n"); | ||
384 | free(path); | ||
385 | fclose(file); | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | hex2u64(vma, §ion->vma); | ||
390 | sec_dso__insert_section(mod->sections, section); | ||
391 | |||
392 | free(path); | ||
393 | fclose(file); | ||
394 | count++; | ||
395 | } | ||
396 | |||
397 | closedir(dir); | ||
398 | free(line); | ||
399 | free(dir_path); | ||
400 | |||
401 | return count; | ||
402 | |||
403 | out_free: | ||
404 | free(dir_path); | ||
405 | |||
406 | out_failure: | ||
407 | return count; | ||
408 | } | ||
409 | |||
410 | static int mod_dso__load_module_paths(struct mod_dso *self) | ||
411 | { | ||
412 | struct utsname uts; | ||
413 | int count = 0, len, err = -1; | ||
414 | char *line = NULL; | ||
415 | FILE *file; | ||
416 | char *dpath, *dir; | ||
417 | size_t n; | ||
418 | |||
419 | if (uname(&uts) < 0) | ||
420 | return err; | ||
421 | |||
422 | len = strlen("/lib/modules/"); | ||
423 | len += strlen(uts.release); | ||
424 | len += strlen("/modules.dep"); | ||
425 | |||
426 | dpath = calloc(1, len + 1); | ||
427 | if (dpath == NULL) | ||
428 | return err; | ||
429 | |||
430 | strcat(dpath, "/lib/modules/"); | ||
431 | strcat(dpath, uts.release); | ||
432 | strcat(dpath, "/modules.dep"); | ||
433 | |||
434 | file = fopen(dpath, "r"); | ||
435 | if (file == NULL) | ||
436 | goto out_failure; | ||
437 | |||
438 | dir = dirname(dpath); | ||
439 | if (!dir) | ||
440 | goto out_failure; | ||
441 | strcat(dir, "/"); | ||
442 | |||
443 | while (!feof(file)) { | ||
444 | struct module *module; | ||
445 | char *name, *path, *tmp; | ||
446 | FILE *modfile; | ||
447 | int line_len; | ||
448 | |||
449 | line_len = getline(&line, &n, file); | ||
450 | if (line_len < 0) | ||
451 | break; | ||
452 | |||
453 | if (!line) | ||
454 | break; | ||
455 | |||
456 | line[--line_len] = '\0'; /* \n */ | ||
457 | |||
458 | path = strchr(line, ':'); | ||
459 | if (!path) | ||
460 | break; | ||
461 | *path = '\0'; | ||
462 | |||
463 | path = strdup(line); | ||
464 | if (!path) | ||
465 | break; | ||
466 | |||
467 | if (!strstr(path, dir)) { | ||
468 | if (strncmp(path, "kernel/", 7)) | ||
469 | break; | ||
470 | |||
471 | free(path); | ||
472 | path = calloc(1, strlen(dir) + strlen(line) + 1); | ||
473 | if (!path) | ||
474 | break; | ||
475 | strcat(path, dir); | ||
476 | strcat(path, line); | ||
477 | } | ||
478 | |||
479 | modfile = fopen(path, "r"); | ||
480 | if (modfile == NULL) | ||
481 | break; | ||
482 | fclose(modfile); | ||
483 | |||
484 | name = strdup(path); | ||
485 | if (!name) | ||
486 | break; | ||
487 | |||
488 | name = strtok(name, "/"); | ||
489 | tmp = name; | ||
490 | |||
491 | while (tmp) { | ||
492 | tmp = strtok(NULL, "/"); | ||
493 | if (tmp) | ||
494 | name = tmp; | ||
495 | } | ||
496 | |||
497 | name = strsep(&name, "."); | ||
498 | if (!name) | ||
499 | break; | ||
500 | |||
501 | /* Quirk: replace '-' with '_' in all modules */ | ||
502 | for (len = strlen(name); len; len--) { | ||
503 | if (*(name+len) == '-') | ||
504 | *(name+len) = '_'; | ||
505 | } | ||
506 | |||
507 | module = module__new(name, path); | ||
508 | if (!module) | ||
509 | break; | ||
510 | mod_dso__insert_module(self, module); | ||
511 | |||
512 | module->sections = sec_dso__new_dso("sections"); | ||
513 | if (!module->sections) | ||
514 | break; | ||
515 | |||
516 | module->active = mod_dso__load_sections(module); | ||
517 | |||
518 | if (module->active > 0) | ||
519 | count++; | ||
520 | } | ||
521 | |||
522 | if (feof(file)) | ||
523 | err = count; | ||
524 | else | ||
525 | fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n"); | ||
526 | |||
527 | out_failure: | ||
528 | if (dpath) | ||
529 | free(dpath); | ||
530 | if (file) | ||
531 | fclose(file); | ||
532 | if (line) | ||
533 | free(line); | ||
534 | |||
535 | return err; | ||
536 | } | ||
537 | |||
538 | int mod_dso__load_modules(struct mod_dso *dso) | ||
539 | { | ||
540 | int err; | ||
541 | |||
542 | err = mod_dso__load_module_paths(dso); | ||
543 | |||
544 | return err; | ||
545 | } | ||