Advertisement
Guest User

Untitled

a guest
Sep 18th, 2014
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.88 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. if (!markers) {
  267. fprintf(stderr, "kallsyms failure: "
  268. "unable to allocate required memory\n");
  269. exit(EXIT_FAILURE);
  270. }
  271.  
  272. output_label("kallsyms_names");
  273. off = 0;
  274. for (i = 0; i < table_cnt; i++) {
  275. if ((i & 0xFF) == 0)
  276. markers[i >> 8] = off;
  277.  
  278. printf("\t.byte 0x%02x", table[i].len);
  279. for (k = 0; k < table[i].len; k++)
  280. printf(", 0x%02x", table[i].sym[k]);
  281. printf("\n");
  282.  
  283. off += table[i].len + 1;
  284. }
  285. printf("\n");
  286.  
  287. output_label("kallsyms_markers");
  288. for (i = 0; i < ((table_cnt + 255) >> 8); i++)
  289. printf("\tPTR\t%d\n", markers[i]);
  290. printf("\n");
  291.  
  292. free(markers);
  293.  
  294. output_label("kallsyms_token_table");
  295. off = 0;
  296. for (i = 0; i < 256; i++) {
  297. best_idx[i] = off;
  298. expand_symbol(best_table[i], best_table_len[i], buf);
  299. printf("\t.asciz\t\"%s\"\n", buf);
  300. off += strlen(buf) + 1;
  301. }
  302. printf("\n");
  303.  
  304. output_label("kallsyms_token_index");
  305. for (i = 0; i < 256; i++)
  306. printf("\t.short\t%d\n", best_idx[i]);
  307. printf("\n");
  308. }
  309.  
  310. /* table lookup compression functions */
  311.  
  312. /* count all the possible tokens in a symbol */
  313. static void learn_symbol(unsigned char *symbol, int len)
  314. {
  315. int i;
  316.  
  317. for (i = 0; i < len – 1; i++)
  318. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
  319. }
  320.  
  321. /* decrease the count for all the possible tokens in a symbol */
  322. static void forget_symbol(unsigned char *symbol, int len)
  323. {
  324. int i;
  325.  
  326. for (i = 0; i < len – 1; i++)
  327. token_profit[ symbol[i] + (symbol[i + 1] << 8) ]–;
  328. }
  329.  
  330. /* remove all the invalid symbols from the table and do the initial token count */
  331. static void build_initial_tok_table(void)
  332. {
  333. unsigned int i, pos;
  334.  
  335. pos = 0;
  336. for (i = 0; i < table_cnt; i++) {
  337. if ( symbol_valid(&table[i]) ) {
  338. if (pos != i)
  339. table[pos] = table[i];
  340. learn_symbol(table[pos].sym, table[pos].len);
  341. pos++;
  342. }
  343. }
  344. table_cnt = pos;
  345. }
  346.  
  347. /* replace a given token in all the valid symbols. Use the sampled symbols
  348. * to update the counts */
  349. static void compress_symbols(unsigned char *str, int idx)
  350. {
  351. unsigned int i, len, size;
  352. unsigned char *p1, *p2;
  353.  
  354. for (i = 0; i < table_cnt; i++) {
  355.  
  356. len = table[i].len;
  357. p1 = table[i].sym;
  358.  
  359. /* find the token on the symbol */
  360. p2 = memmem(p1, len, str, 2);
  361. if (!p2) continue;
  362.  
  363. /* decrease the counts for this symbol’s tokens */
  364. forget_symbol(table[i].sym, len);
  365.  
  366. size = len;
  367.  
  368. do {
  369. *p2 = idx;
  370. p2++;
  371. size -= (p2 – p1);
  372. memmove(p2, p2 + 1, size);
  373. p1 = p2;
  374. len–;
  375.  
  376. if (size < 2) break;
  377.  
  378. /* find the token on the symbol */
  379. p2 = memmem(p1, size, str, 2);
  380.  
  381. } while (p2);
  382.  
  383. table[i].len = len;
  384.  
  385. /* increase the counts for this symbol’s new tokens */
  386. learn_symbol(table[i].sym, len);
  387. }
  388. }
  389.  
  390. /* search the token with the maximum profit */
  391. static int find_best_token(void)
  392. {
  393. int i, best, bestprofit;
  394.  
  395. bestprofit=-10000;
  396. best = 0;
  397.  
  398. for (i = 0; i < 0×10000; i++) {
  399. if (token_profit[i] > bestprofit) {
  400. best = i;
  401. bestprofit = token_profit[i];
  402. }
  403. }
  404. return best;
  405. }
  406.  
  407. /* this is the core of the algorithm: calculate the "best" table */
  408. static void optimize_result(void)
  409. {
  410. int i, best;
  411.  
  412. /* using the " symbol last allows compress_symbols to use standard
  413. * fast string functions */
  414. for (i = 255; i >= 0; i–) {
  415.  
  416. /* if this table slot is empty (it is not used by an actual
  417. * original char code */
  418. if (!best_table_len[i]) {
  419.  
  420. /* find the token with the breates profit value */
  421. best = find_best_token();
  422.  
  423. /* place it in the "best" table */
  424. best_table_len[i] = 2;
  425. best_table[i][0] = best & 0xFF;
  426. best_table[i][1] = (best >> 8) & 0xFF;
  427.  
  428. /* replace this token in all the valid symbols */
  429. compress_symbols(best_table[i], i);
  430. }
  431. }
  432. }
  433.  
  434. /* start by placing the symbols that are actually used on the table */
  435. static void insert_real_symbols_in_table(void)
  436. {
  437. unsigned int i, j, c;
  438.  
  439. memset(best_table, 0, sizeof(best_table));
  440. memset(best_table_len, 0, sizeof(best_table_len));
  441.  
  442. for (i = 0; i < table_cnt; i++) {
  443. for (j = 0; j < table[i].len; j++) {
  444. c = table[i].sym[j];
  445. best_table[c][0]=c;
  446. best_table_len[c]=1;
  447. }
  448. }
  449. }
  450.  
  451. static void optimize_token_table(void)
  452. {
  453. build_initial_tok_table();
  454.  
  455. insert_real_symbols_in_table();
  456.  
  457. /* When valid symbol is not registered, exit to error */
  458. if (!table_cnt) {
  459. fprintf(stderr, "No valid symbol.\n");
  460. exit(1);
  461. }
  462.  
  463. optimize_result();
  464. }
  465.  
  466. int main(int argc, char **argv)
  467. {
  468. if (argc >= 2) {
  469. int i;
  470. for (i = 1; i < argc; i++) {
  471. if(strcmp(argv[i], "–all-symbols") == 0)
  472. all_symbols = 1;
  473. else if (strncmp(argv[i], "–symbol-prefix=", 16) == 0) {
  474. char *p = &argv[i][16];
  475. /* skip quote */
  476. if ((*p == ‘"‘ && *(p+2) == ‘"‘) || (*p == ‘\" && *(p+2) == ‘\"))
  477. p++;
  478. symbol_prefix_char = *p;
  479. } else
  480. usage();
  481. }
  482. } else if (argc != 1)
  483. usage();
  484.  
  485. read_map(stdin);
  486. optimize_token_table();
  487. write_src();
  488.  
  489. return 0;
  490. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement