at v2.6.32 9.9 kB view raw
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 13static 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 28struct 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 41static void sec_dso__delete_section(struct section *self) 42{ 43 free(((void *)self)); 44} 45 46void 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 59void sec_dso__delete_self(struct sec_dso *self) 60{ 61 sec_dso__delete_sections(self); 62 free(self); 63} 64 65static 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 84struct 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 116static 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 122size_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 135static 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 156out_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 170struct 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 183static void mod_dso__delete_module(struct module *self) 184{ 185 free(((void *)self)); 186} 187 188void 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 201void mod_dso__delete_self(struct mod_dso *self) 202{ 203 mod_dso__delete_modules(self); 204 free(self); 205} 206 207static 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 226struct 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 258static 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 263size_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 279static 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 300out_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 312static 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, &section->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 403out_free: 404 free(dir_path); 405 406out_failure: 407 return count; 408} 409 410static 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 527out_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 538int 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}