module.c 9.2 KB

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