module.c 9.7 KB

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