Advertisement
meninbox

2.6.32-458

Sep 9th, 2014
1,317
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.51 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7.  
  8. #define KSYM_NAME_LEN 127
  9.  
  10. struct sym_entry {
  11. unsigned long long addr;
  12. unsigned int len;
  13. unsigned char *sym;
  14. };
  15.  
  16. static struct sym_entry *table;
  17. static unsigned int table_size, table_cnt;
  18. static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _***tratext, _eextratext;
  19. static int all_symbols = 0;
  20. static char symbol_prefix_char = ”;
  21.  
  22. int token_profit[0x10000];
  23.  
  24. /* the table that holds the result of the compression */
  25. unsigned char best_table[256][2];
  26. unsigned char best_table_len[256];
  27.  
  28. static void usage(void)
  29. {
  30. fprintf(stderr, “Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n”);
  31. exit(1);
  32. }
  33.  
  34. /*
  35. * This ignores the intensely annoying “mapping symbols” found
  36. * in ARM ELF files: $a, $t and $d.
  37. */
  38. static inline int is_arm_mapping_symbol(const char *str)
  39. {
  40. return str[0] == ‘$’ && strchr(“atd”, str[1])
  41. && (str[2] == ” || str[2] == ‘.’);
  42. }
  43.  
  44. static int read_symbol(FILE *in, struct sym_entry *s)
  45. {
  46. char str[500];
  47. char *sym, stype;
  48. int rc;
  49.  
  50. rc = fscanf(in, “%llx %c %499s\n”, &s->addr, &stype, str);
  51. if (rc != 3) {
  52. if (rc != EOF) {
  53. /* skip line */
  54. fgets(str, 500, in);
  55. }
  56. return -1;
  57. }
  58.  
  59. sym = str;
  60. /* skip prefix char */
  61. if (symbol_prefix_char && str[0] == symbol_prefix_char)
  62. sym++;
  63.  
  64. /* Ignore most absolute/undefined (?) symbols. */
  65. if (strcmp(sym, “_text”) == 0)
  66. _text = s->addr;
  67. else if (strcmp(sym, “_stext”) == 0)
  68. _stext = s->addr;
  69. else if (strcmp(sym, “_etext”) == 0)
  70. _etext = s->addr;
  71. else if (strcmp(sym, “_sinittext”) == 0)
  72. _sinittext = s->addr;
  73. else if (strcmp(sym, “_einittext”) == 0)
  74. _einittext = s->addr;
  75. else if (strcmp(sym, “_***tratext”) == 0)
  76. _***tratext = s->addr;
  77. else if (strcmp(sym, “_eextratext”) == 0)
  78. _eextratext = s->addr;
  79. else if (toupper(stype) == ‘A’)
  80. {
  81. /* Keep these useful absolute symbols */
  82. if (strcmp(sym, “__kernel_syscall_via_break”) &&
  83. strcmp(sym, “__kernel_syscall_via_epc”) &&
  84. strcmp(sym, “__kernel_sigtramp”) &&
  85. strcmp(sym, “__gp”))
  86. return -1;
  87.  
  88. }
  89. else if (toupper(stype) == ‘U’ ||
  90. is_arm_mapping_symbol(sym))
  91. return -1;
  92. /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
  93. else if (str[0] == ‘$’)
  94. return -1;
  95.  
  96. /* include the type field in the symbol name, so that it gets
  97. * compressed together */
  98. s->len = strlen(str) + 1;
  99. s->sym = malloc(s->len + 1);
  100. if (!s->sym) {
  101. fprintf(stderr, “kallsyms failure: “
  102. “unable to allocate required amount of memory\n”);
  103. exit(EXIT_FAILURE);
  104. }
  105. strcpy((char *)s->sym + 1, str);
  106. s->sym[0] = stype;
  107.  
  108. return 0;
  109. }
  110.  
  111. static int symbol_valid(struct sym_entry *s)
  112. {
  113. /* Symbols which vary between passes. Passes 1 and 2 must have
  114. * identical symbol lists. The kallsyms_* symbols below are only added
  115. * after pass 1, they would be included in pass 2 when –all-symbols is
  116. * specified so exclude them to get a stable symbol list.
  117. */
  118. static char *special_symbols[] = {
  119. “kallsyms_addresses”,
  120. “kallsyms_num_syms”,
  121. “kallsyms_names”,
  122. “kallsyms_markers”,
  123. “kallsyms_token_table”,
  124. “kallsyms_token_index”,
  125.  
  126. /* Exclude linker generated symbols which vary between passes */
  127. “_SDA_BASE_”, /* ppc */
  128. “_SDA2_BASE_”, /* ppc */
  129. NULL };
  130. int i;
  131. int offset = 1;
  132.  
  133. /* skip prefix char */
  134. if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
  135. offset++;
  136.  
  137. /* if –all-symbols is not specified, then symbols outside the text
  138. * and inittext sections are discarded */
  139. if (!all_symbols) {
  140. if ((s->addr < _stext || s->addr > _etext)
  141. && (s->addr < _sinittext || s->addr > _einittext)
  142. && (s->addr < _***tratext || s->addr > _eextratext))
  143. return 0;
  144. /* Corner case. Discard any symbols with the same value as
  145. * _etext _einittext or _eextratext; they can move between pass
  146. * 1 and 2 when the kallsyms data are added. If these symbols
  147. * move then they may get dropped in pass 2, which breaks the
  148. * kallsyms rules.
  149. */
  150. if ((s->addr == _etext && strcmp((char*)s->sym + offset, “_etext”)) ||
  151. (s->addr == _einittext && strcmp((char*)s->sym + offset, “_einittext”)) ||
  152. (s->addr == _eextratext && strcmp((char*)s->sym + offset, “_eextratext”)))
  153. return 0;
  154. }
  155.  
  156. /* Exclude symbols which vary between passes. */
  157. if (strstr((char *)s->sym + offset, “_compiled.”))
  158. return 0;
  159.  
  160. for (i = 0; special_symbols[i]; i++)
  161. if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
  162. return 0;
  163.  
  164. return 1;
  165. }
  166.  
  167. static void read_map(FILE *in)
  168. {
  169. while (!feof(in)) {
  170. if (table_cnt >= table_size) {
  171. table_size += 10000;
  172. table = realloc(table, sizeof(*table) * table_size);
  173. if (!table) {
  174. fprintf(stderr, “out of memory\n”);
  175. exit (1);
  176. }
  177. }
  178. if (read_symbol(in, &table[table_cnt]) == 0)
  179. table_cnt++;
  180. }
  181. }
  182.  
  183. static void output_label(char *label)
  184. {
  185. if (symbol_prefix_char)
  186. printf(“.globl %c%s\n”, symbol_prefix_char, label);
  187. else
  188. printf(“.globl %s\n”, label);
  189. printf(“\tALGN\n”);
  190. if (symbol_prefix_char)
  191. printf(“%c%s:\n”, symbol_prefix_char, label);
  192. else
  193. printf(“%s:\n”, label);
  194. }
  195.  
  196. /* uncompress a compressed symbol. When this function is called, the best table
  197. * might still be compressed itself, so the function needs to be recursive */
  198. static int expand_symbol(unsigned char *data, int len, char *result)
  199. {
  200. int c, rlen, total=0;
  201.  
  202. while (len) {
  203. c = *data;
  204. /* if the table holds a single char that is the same as the one
  205. * we are looking for, then end the search */
  206. if (best_table[c][0]==c && best_table_len[c]==1) {
  207. *result++ = c;
  208. total++;
  209. } else {
  210. /* if not, recurse and expand */
  211. rlen = expand_symbol(best_table[c], best_table_len[c], result);
  212. total += rlen;
  213. result += rlen;
  214. }
  215. data++;
  216. len–;
  217. }
  218. *result=0;
  219.  
  220. return total;
  221. }
  222.  
  223. static void write_src(void)
  224. {
  225. unsigned int i, k, off;
  226. unsigned int best_idx[256];
  227. unsigned int *markers;
  228. char buf[KSYM_NAME_LEN+1];
  229.  
  230. printf(“#include <asm/types.h>\n”);
  231. printf(“#if BITS_PER_LONG == 64\n”);
  232. printf(“#define PTR .quad\n”);
  233. printf(“#define ALGN .align 8\n”);
  234. printf(“#else\n”);
  235. printf(“#define PTR .long\n”);
  236. printf(“#define ALGN .align 4\n”);
  237. printf(“#endif\n”);
  238.  
  239. printf(“.data\n”);
  240.  
  241. /* Provide proper symbols relocatability by their ‘_text’
  242. * relativeness. The symbol names cannot be used to construct
  243. * normal symbol references as the list of symbols contains
  244. * symbols that are declared static and are private to their
  245. * .o files. This prevents .tmp_kallsyms.o or any other
  246. * object from referencing them.
  247. */
  248. output_label(“kallsyms_addresses”);
  249. for (i = 0; i < table_cnt; i++) {
  250. if (toupper(table[i].sym[0]) != ‘A’) {
  251. printf(“\tPTR\t_text + %#llx\n”,
  252. table[i].addr – _text);
  253. } else {
  254. printf(“\tPTR\t%#llx\n”, table[i].addr);
  255. }
  256. }
  257. printf(“\n”);
  258.  
  259. output_label(“kallsyms_num_syms”);
  260. printf(“\tPTR\t%d\n”, table_cnt);
  261. printf(“\n”);
  262.  
  263. /* table of offset markers, that give the offset in the compressed stream
  264. * every 256 symbols */
  265. markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
  266.  
  267.  
  268.  
  269. if (!markers) {
  270. fprintf(stderr, “kallsyms failure: “
  271. “unable to allocate required memory\n”);
  272. exit(EXIT_FAILURE);
  273. }
  274.  
  275. output_label(“kallsyms_names”);
  276. off = 0;
  277. for (i = 0; i < table_cnt; i++) {
  278. if ((i & 0xFF) == 0)
  279. markers[i >> 8] = off;
  280.  
  281. printf(“\t.byte 0x%02x”, table[i].len);
  282. for (k = 0; k < table[i].len; k++)
  283. printf(“, 0x%02x”, table[i].sym[k]);
  284. printf(“\n”);
  285.  
  286. off += table[i].len + 1;
  287. }
  288. printf(“\n”);
  289.  
  290. output_label(“kallsyms_markers”);
  291. for (i = 0; i < ((table_cnt + 255) >> 8); i++)
  292. printf(“\tPTR\t%d\n”, markers[i]);
  293. printf(“\n”);
  294.  
  295. free(markers);
  296.  
  297. output_label(“kallsyms_token_table”);
  298. off = 0;
  299. for (i = 0; i < 256; i++) {
  300. best_idx[i] = off;
  301. expand_symbol(best_table[i], best_table_len[i], buf);
  302. printf(“\t.asciz\t\”%s\”\n”, buf);
  303. off += strlen(buf) + 1;
  304. }
  305. printf(“\n”);
  306.  
  307. output_label(“kallsyms_token_index”);
  308. for (i = 0; i < 256; i++)
  309. printf(“\t.short\t%d\n”, best_idx[i]);
  310. printf(“\n”);
  311. }
  312.  
  313. /* table lookup compression functions */
  314.  
  315. /* count all the possible tokens in a symbol */
  316. static void learn_symbol(unsigned char *symbol, int len)
  317. {
  318. int i;
  319.  
  320. for (i = 0; i < len – 1; i++)
  321. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
  322. }
  323.  
  324. /* decrease the count for all the possible tokens in a symbol */
  325. static void forget_symbol(unsigned char *symbol, int len)
  326. {
  327. int i;
  328.  
  329. for (i = 0; i < len – 1; i++)
  330. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]–;
  331. }
  332.  
  333. /* remove all the invalid symbols from the table and do the initial token count */
  334. static void build_initial_tok_table(void)
  335. {
  336. unsigned int i, pos;
  337.  
  338. pos = 0;
  339. for (i = 0; i < table_cnt; i++) {
  340. if ( symbol_valid(&table[i]) ) {
  341. if (pos != i)
  342. table[pos] = table[i];
  343. learn_symbol(table[pos].sym, table[pos].len);
  344. pos++;
  345. }
  346. }
  347. table_cnt = pos;
  348. }
  349.  
  350. /* replace a given token in all the valid symbols. Use the sampled symbols
  351. * to update the counts */
  352. static void compress_symbols(unsigned char *str, int idx)
  353. {
  354. unsigned int i, len, size;
  355. unsigned char *p1, *p2;
  356.  
  357. for (i = 0; i < table_cnt; i++) {
  358.  
  359. len = table[i].len;
  360. p1 = table[i].sym;
  361.  
  362. /* find the token on the symbol */
  363. p2 = memmem(p1, len, str, 2);
  364. if (!p2) continue;
  365.  
  366. /* decrease the counts for this symbol’s tokens */
  367. forget_symbol(table[i].sym, len);
  368.  
  369. size = len;
  370.  
  371. do {
  372. *p2 = idx;
  373. p2++;
  374. size -= (p2 – p1);
  375. memmove(p2, p2 + 1, size);
  376. p1 = p2;
  377. len–;
  378.  
  379. if (size < 2) break;
  380.  
  381. /* find the token on the symbol */
  382. p2 = memmem(p1, size, str, 2);
  383.  
  384. } while (p2);
  385.  
  386. table[i].len = len;
  387.  
  388. /* increase the counts for this symbol’s new tokens */
  389. learn_symbol(table[i].sym, len);
  390. }
  391. }
  392.  
  393. /* search the token with the maximum profit */
  394. static int find_best_token(void)
  395. {
  396. int i, best, bestprofit;
  397.  
  398. bestprofit=-10000;
  399. best = 0;
  400.  
  401. for (i = 0; i < 0×10000; i++) {
  402. if (token_profit[i] > bestprofit) {
  403. best = i;
  404. bestprofit = token_profit[i];
  405. }
  406. }
  407. return best;
  408. }
  409.  
  410. /* this is the core of the algorithm: calculate the “best” table */
  411. static void optimize_result(void)
  412. {
  413. int i, best;
  414.  
  415. /* using the ” symbol last allows compress_symbols to use standard
  416. * fast string functions */
  417. for (i = 255; i >= 0; i–) {
  418.  
  419. /* if this table slot is empty (it is not used by an actual
  420. * original char code */
  421. if (!best_table_len[i]) {
  422.  
  423. /* find the token with the breates profit value */
  424. best = find_best_token();
  425.  
  426. /* place it in the “best” table */
  427. best_table_len[i] = 2;
  428. best_table[i][0] = best & 0xFF;
  429. best_table[i][1] = (best >> 8) & 0xFF;
  430.  
  431. /* replace this token in all the valid symbols */
  432. compress_symbols(best_table[i], i);
  433. }
  434. }
  435. }
  436.  
  437. /* start by placing the symbols that are actually used on the table */
  438. static void insert_real_symbols_in_table(void)
  439. {
  440. unsigned int i, j, c;
  441.  
  442. memset(best_table, 0, sizeof(best_table));
  443. memset(best_table_len, 0, sizeof(best_table_len));
  444.  
  445. for (i = 0; i < table_cnt; i++) {
  446. for (j = 0; j < table[i].len; j++) {
  447. c = table[i].sym[j];
  448. best_table[c][0]=c;
  449. best_table_len[c]=1;
  450. }
  451. }
  452. }
  453.  
  454. static void optimize_token_table(void)
  455. {
  456. build_initial_tok_table();
  457.  
  458. insert_real_symbols_in_table();
  459.  
  460. /* When valid symbol is not registered, exit to error */
  461. if (!table_cnt) {
  462. fprintf(stderr, “No valid symbol.\n”);
  463. exit(1);
  464. }
  465.  
  466. optimize_result();
  467. }
  468.  
  469. int main(int argc, char **argv)
  470. {
  471. if (argc >= 2) {
  472. int i;
  473. for (i = 1; i < argc; i++) {
  474. if(strcmp(argv[i], “–all-symbols”) == 0)
  475. all_symbols = 1;
  476. else if (strncmp(argv[i], “–symbol-prefix=”, 16) == 0) {
  477. char *p = &argv[i][16];
  478. /* skip quote */
  479. if ((*p == ‘”‘ && *(p+2) == ‘”‘) || (*p == ‘\” && *(p+2) == ‘\”))
  480. p++;
  481. symbol_prefix_char = *p;
  482. } else
  483. usage();
  484. }
  485. } else if (argc != 1)
  486. usage();
  487.  
  488. read_map(stdin);
  489. optimize_token_table();
  490. write_src();
  491.  
  492. return 0;
  493. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement