at v2.6.31 509 lines 9.4 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 <gelf.h> 8#include <elf.h> 9#include <dirent.h> 10#include <sys/utsname.h> 11 12static unsigned int crc32(const char *p, unsigned int len) 13{ 14 int i; 15 unsigned int crc = 0; 16 17 while (len--) { 18 crc ^= *p++; 19 for (i = 0; i < 8; i++) 20 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); 21 } 22 return crc; 23} 24 25/* module section methods */ 26 27struct sec_dso *sec_dso__new_dso(const char *name) 28{ 29 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1); 30 31 if (self != NULL) { 32 strcpy(self->name, name); 33 self->secs = RB_ROOT; 34 self->find_section = sec_dso__find_section; 35 } 36 37 return self; 38} 39 40static void sec_dso__delete_section(struct section *self) 41{ 42 free(((void *)self)); 43} 44 45void sec_dso__delete_sections(struct sec_dso *self) 46{ 47 struct section *pos; 48 struct rb_node *next = rb_first(&self->secs); 49 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); 55 } 56} 57 58void sec_dso__delete_self(struct sec_dso *self) 59{ 60 sec_dso__delete_sections(self); 61 free(self); 62} 63 64static void sec_dso__insert_section(struct sec_dso *self, struct section *sec) 65{ 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; 70 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; 78 } 79 rb_link_node(&sec->rb_node, parent, p); 80 rb_insert_color(&sec->rb_node, &self->secs); 81} 82 83struct section *sec_dso__find_section(struct sec_dso *self, const char *name) 84{ 85 struct rb_node *n; 86 u64 hash; 87 int len; 88 89 if (self == NULL) 90 return NULL; 91 92 len = strlen(name); 93 hash = crc32(name, len); 94 95 n = self->secs.rb_node; 96 97 while (n) { 98 struct section *s = rb_entry(n, struct section, rb_node); 99 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); 109 } 110 } 111 112 return NULL; 113} 114 115static size_t sec_dso__fprintf_section(struct section *self, FILE *fp) 116{ 117 return fprintf(fp, "name:%s vma:%llx path:%s\n", 118 self->name, self->vma, self->path); 119} 120 121size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp) 122{ 123 size_t ret = fprintf(fp, "dso: %s\n", self->name); 124 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); 129 } 130 131 return ret; 132} 133 134static struct section *section__new(const char *name, const char *path) 135{ 136 struct section *self = calloc(1, sizeof(*self)); 137 138 if (!self) 139 goto out_failure; 140 141 self->name = calloc(1, strlen(name) + 1); 142 if (!self->name) 143 goto out_failure; 144 145 self->path = calloc(1, strlen(path) + 1); 146 if (!self->path) 147 goto out_failure; 148 149 strcpy(self->name, name); 150 strcpy(self->path, path); 151 self->hash = crc32(self->name, strlen(name)); 152 153 return self; 154 155out_failure: 156 if (self) { 157 if (self->name) 158 free(self->name); 159 if (self->path) 160 free(self->path); 161 free(self); 162 } 163 164 return NULL; 165} 166 167/* module methods */ 168 169struct mod_dso *mod_dso__new_dso(const char *name) 170{ 171 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1); 172 173 if (self != NULL) { 174 strcpy(self->name, name); 175 self->mods = RB_ROOT; 176 self->find_module = mod_dso__find_module; 177 } 178 179 return self; 180} 181 182static void mod_dso__delete_module(struct module *self) 183{ 184 free(((void *)self)); 185} 186 187void mod_dso__delete_modules(struct mod_dso *self) 188{ 189 struct module *pos; 190 struct rb_node *next = rb_first(&self->mods); 191 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); 197 } 198} 199 200void mod_dso__delete_self(struct mod_dso *self) 201{ 202 mod_dso__delete_modules(self); 203 free(self); 204} 205 206static void mod_dso__insert_module(struct mod_dso *self, struct module *mod) 207{ 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; 212 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; 220 } 221 rb_link_node(&mod->rb_node, parent, p); 222 rb_insert_color(&mod->rb_node, &self->mods); 223} 224 225struct module *mod_dso__find_module(struct mod_dso *self, const char *name) 226{ 227 struct rb_node *n; 228 u64 hash; 229 int len; 230 231 if (self == NULL) 232 return NULL; 233 234 len = strlen(name); 235 hash = crc32(name, len); 236 237 n = self->mods.rb_node; 238 239 while (n) { 240 struct module *m = rb_entry(n, struct module, rb_node); 241 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); 251 } 252 } 253 254 return NULL; 255} 256 257static size_t mod_dso__fprintf_module(struct module *self, FILE *fp) 258{ 259 return fprintf(fp, "name:%s path:%s\n", self->name, self->path); 260} 261 262size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp) 263{ 264 struct rb_node *nd; 265 size_t ret; 266 267 ret = fprintf(fp, "dso: %s\n", self->name); 268 269 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) { 270 struct module *pos = rb_entry(nd, struct module, rb_node); 271 272 ret += mod_dso__fprintf_module(pos, fp); 273 } 274 275 return ret; 276} 277 278static struct module *module__new(const char *name, const char *path) 279{ 280 struct module *self = calloc(1, sizeof(*self)); 281 282 if (!self) 283 goto out_failure; 284 285 self->name = calloc(1, strlen(name) + 1); 286 if (!self->name) 287 goto out_failure; 288 289 self->path = calloc(1, strlen(path) + 1); 290 if (!self->path) 291 goto out_failure; 292 293 strcpy(self->name, name); 294 strcpy(self->path, path); 295 self->hash = crc32(self->name, strlen(name)); 296 297 return self; 298 299out_failure: 300 if (self) { 301 if (self->name) 302 free(self->name); 303 if (self->path) 304 free(self->path); 305 free(self); 306 } 307 308 return NULL; 309} 310 311static int mod_dso__load_sections(struct module *mod) 312{ 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; 319 320 path_len = strlen("/sys/module/"); 321 path_len += strlen(mod->name); 322 path_len += strlen("/sections/"); 323 324 dir_path = calloc(1, path_len + 1); 325 if (dir_path == NULL) 326 goto out_failure; 327 328 strcat(dir_path, "/sys/module/"); 329 strcat(dir_path, mod->name); 330 strcat(dir_path, "/sections/"); 331 332 dir = opendir(dir_path); 333 if (dir == NULL) 334 goto out_free; 335 336 while ((entry = readdir(dir))) { 337 struct section *section; 338 char *path, *vma; 339 int line_len; 340 FILE *file; 341 342 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) 343 continue; 344 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); 350 351 file = fopen(path, "r"); 352 if (file == NULL) { 353 free(path); 354 break; 355 } 356 357 line_len = getline(&line, &n, file); 358 if (line_len < 0) { 359 free(path); 360 fclose(file); 361 break; 362 } 363 364 if (!line) { 365 free(path); 366 fclose(file); 367 break; 368 } 369 370 line[--line_len] = '\0'; /* \n */ 371 372 vma = strstr(line, "0x"); 373 if (!vma) { 374 free(path); 375 fclose(file); 376 break; 377 } 378 vma += 2; 379 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; 386 } 387 388 hex2u64(vma, &section->vma); 389 sec_dso__insert_section(mod->sections, section); 390 391 free(path); 392 fclose(file); 393 count++; 394 } 395 396 closedir(dir); 397 free(line); 398 free(dir_path); 399 400 return count; 401 402out_free: 403 free(dir_path); 404 405out_failure: 406 return count; 407} 408 409static int mod_dso__load_module_paths(struct mod_dso *self) 410{ 411 struct utsname uts; 412 int count = 0, len; 413 char *line = NULL; 414 FILE *file; 415 char *path; 416 size_t n; 417 418 if (uname(&uts) < 0) 419 goto out_failure; 420 421 len = strlen("/lib/modules/"); 422 len += strlen(uts.release); 423 len += strlen("/modules.dep"); 424 425 path = calloc(1, len); 426 if (path == NULL) 427 goto out_failure; 428 429 strcat(path, "/lib/modules/"); 430 strcat(path, uts.release); 431 strcat(path, "/modules.dep"); 432 433 file = fopen(path, "r"); 434 free(path); 435 if (file == NULL) 436 goto out_failure; 437 438 while (!feof(file)) { 439 char *path, *name, *tmp; 440 struct module *module; 441 int line_len, len; 442 443 line_len = getline(&line, &n, file); 444 if (line_len < 0) 445 break; 446 447 if (!line) 448 goto out_failure; 449 450 line[--line_len] = '\0'; /* \n */ 451 452 path = strtok(line, ":"); 453 if (!path) 454 goto out_failure; 455 456 name = strdup(path); 457 name = strtok(name, "/"); 458 459 tmp = name; 460 461 while (tmp) { 462 tmp = strtok(NULL, "/"); 463 if (tmp) 464 name = tmp; 465 } 466 name = strsep(&name, "."); 467 468 /* Quirk: replace '-' with '_' in sound modules */ 469 for (len = strlen(name); len; len--) { 470 if (*(name+len) == '-') 471 *(name+len) = '_'; 472 } 473 474 module = module__new(name, path); 475 if (!module) { 476 fprintf(stderr, "load_module_paths: allocation error\n"); 477 goto out_failure; 478 } 479 mod_dso__insert_module(self, module); 480 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; 485 } 486 487 module->active = mod_dso__load_sections(module); 488 489 if (module->active > 0) 490 count++; 491 } 492 493 free(line); 494 fclose(file); 495 496 return count; 497 498out_failure: 499 return -1; 500} 501 502int mod_dso__load_modules(struct mod_dso *dso) 503{ 504 int err; 505 506 err = mod_dso__load_module_paths(dso); 507 508 return err; 509}