Advertisement
virushsality

2.6.32 x86_64

Dec 12th, 2015
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.05 KB | None | 0 0
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6.  
  7. #define KSYM_NAME_LEN 127
  8.  
  9.  
  10. struct sym_entry {
  11. unsigned long long addr;
  12. unsigned int len;
  13. unsigned char *sym;
  14. };
  15.  
  16.  
  17. static struct sym_entry *table;
  18. static unsigned int table_size, table_cnt;
  19. static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
  20. static int all_symbols = 0;
  21. static char symbol_prefix_char = '\0';
  22.  
  23. int token_profit[0x10000];
  24.  
  25. /* the table that holds the result of the compression */
  26. unsigned char best_table[256][2];
  27. unsigned char best_table_len[256];
  28.  
  29.  
  30. static void usage(void)
  31. {
  32. fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
  33. exit(1);
  34. }
  35.  
  36. /*
  37. * This ignores the intensely annoying "mapping symbols" found
  38. * in ARM ELF files: $a, $t and $d.
  39. */
  40. static inline int is_arm_mapping_symbol(const char *str)
  41. {
  42. return str[0] == '$' && strchr("atd", str[1])
  43. && (str[2] == '\0' || str[2] == '.');
  44. }
  45.  
  46. static int read_symbol(FILE *in, struct sym_entry *s)
  47. {
  48. char str[500];
  49. char *sym, stype;
  50. int rc;
  51.  
  52. rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
  53. if (rc != 3) {
  54. if (rc != EOF) {
  55. /* skip line */
  56. fgets(str, 500, in);
  57. }
  58. return -1;
  59. }
  60.  
  61. sym = str;
  62. /* skip prefix char */
  63. if (symbol_prefix_char && str[0] == symbol_prefix_char)
  64. sym++;
  65.  
  66. /* Ignore most absolute/undefined (?) symbols. */
  67. if (strcmp(sym, "_text") == 0)
  68. _text = s->addr;
  69. else if (strcmp(sym, "_stext") == 0)
  70. _stext = s->addr;
  71. else if (strcmp(sym, "_etext") == 0)
  72. _etext = s->addr;
  73. else if (strcmp(sym, "_sinittext") == 0)
  74. _sinittext = s->addr;
  75. else if (strcmp(sym, "_einittext") == 0)
  76. _einittext = s->addr;
  77. else if (strcmp(sym, "_sextratext") == 0)
  78. _sextratext = s->addr;
  79. else if (strcmp(sym, "_eextratext") == 0)
  80. _eextratext = s->addr;
  81. else if (toupper(stype) == 'A')
  82. {
  83. /* Keep these useful absolute symbols */
  84. if (strcmp(sym, "__kernel_syscall_via_break") &&
  85. strcmp(sym, "__kernel_syscall_via_epc") &&
  86. strcmp(sym, "__kernel_sigtramp") &&
  87. strcmp(sym, "__gp"))
  88. return -1;
  89.  
  90. }
  91. else if (toupper(stype) == 'U' ||
  92. is_arm_mapping_symbol(sym))
  93. return -1;
  94. /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
  95. else if (str[0] == '$')
  96. return -1;
  97.  
  98. /* include the type field in the symbol name, so that it gets
  99. * compressed together */
  100. s->len = strlen(str) + 1;
  101. s->sym = malloc(s->len + 1);
  102. if (!s->sym) {
  103. fprintf(stderr, "kallsyms failure: "
  104. "unable to allocate required amount of memory\n");
  105. exit(EXIT_FAILURE);
  106. }
  107. strcpy((char *)s->sym + 1, str);
  108. s->sym[0] = stype;
  109.  
  110. return 0;
  111. }
  112.  
  113. static int symbol_valid(struct sym_entry *s)
  114. {
  115. /* Symbols which vary between passes. Passes 1 and 2 must have
  116. * identical symbol lists. The kallsyms_* symbols below are only added
  117. * after pass 1, they would be included in pass 2 when --all-symbols is
  118. * specified so exclude them to get a stable symbol list.
  119. */
  120. static char *special_symbols[] = {
  121. "kallsyms_addresses",
  122. "kallsyms_num_syms",
  123. "kallsyms_names",
  124. "kallsyms_markers",
  125. "kallsyms_token_table",
  126. "kallsyms_token_index",
  127.  
  128. /* Exclude linker generated symbols which vary between passes */
  129. "_SDA_BASE_", /* ppc */
  130. "_SDA2_BASE_", /* ppc */
  131. NULL };
  132. int i;
  133. int offset = 1;
  134.  
  135. /* skip prefix char */
  136. if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
  137. offset++;
  138.  
  139. /* if --all-symbols is not specified, then symbols outside the text
  140. * and inittext sections are discarded */
  141. if (!all_symbols) {
  142. if ((s->addr < _stext || s->addr > _etext)
  143. && (s->addr < _sinittext || s->addr > _einittext)
  144. && (s->addr < _sextratext || s->addr > _eextratext))
  145. return 0;
  146. /* Corner case. Discard any symbols with the same value as
  147. * _etext _einittext or _eextratext; they can move between pass
  148. * 1 and 2 when the kallsyms data are added. If these symbols
  149. * move then they may get dropped in pass 2, which breaks the
  150. * kallsyms rules.
  151. */
  152. if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
  153. (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
  154. (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
  155. return 0;
  156. }
  157.  
  158. /* Exclude symbols which vary between passes. */
  159. if (strstr((char *)s->sym + offset, "_compiled."))
  160. return 0;
  161.  
  162. for (i = 0; special_symbols[i]; i++)
  163. if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
  164. return 0;
  165.  
  166. return 1;
  167. }
  168.  
  169. static void read_map(FILE *in)
  170. {
  171. while (!feof(in)) {
  172. if (table_cnt >= table_size) {
  173. table_size += 10000;
  174. table = realloc(table, sizeof(*table) * table_size);
  175. if (!table) {
  176. fprintf(stderr, "out of memory\n");
  177. exit (1);
  178. }
  179. }
  180. if (read_symbol(in, &table[table_cnt]) == 0)
  181. table_cnt++;
  182. }
  183. }
  184.  
  185. static void output_label(char *label)
  186. {
  187. if (symbol_prefix_char)
  188. printf(".globl %c%s\n", symbol_prefix_char, label);
  189. else
  190. printf(".globl %s\n", label);
  191. printf("\tALGN\n");
  192. if (symbol_prefix_char)
  193. printf("%c%s:\n", symbol_prefix_char, label);
  194. else
  195. printf("%s:\n", label);
  196. }
  197.  
  198. /* uncompress a compressed symbol. When this function is called, the best table
  199. * might still be compressed itself, so the function needs to be recursive */
  200. static int expand_symbol(unsigned char *data, int len, char *result)
  201. {
  202. int c, rlen, total=0;
  203.  
  204. while (len) {
  205. c = *data;
  206. /* if the table holds a single char that is the same as the one
  207. * we are looking for, then end the search */
  208. if (best_table[c][0]==c && best_table_len[c]==1) {
  209. *result++ = c;
  210. total++;
  211. } else {
  212. /* if not, recurse and expand */
  213. rlen = expand_symbol(best_table[c], best_table_len[c], result);
  214. total += rlen;
  215. result += rlen;
  216. }
  217. data++;
  218. len--;
  219. }
  220. *result=0;
  221.  
  222. return total;
  223. }
  224.  
  225. static void write_src(void)
  226. {
  227. unsigned int i, k, off;
  228. unsigned int best_idx[256];
  229. unsigned int *markers;
  230. char buf[KSYM_NAME_LEN+1];
  231.  
  232. printf("#include <asm/types.h>\n");
  233. printf("#if BITS_PER_LONG == 64\n");
  234. printf("#define PTR .quad\n");
  235. printf("#define ALGN .align 8\n");
  236. printf("#else\n");
  237. printf("#define PTR .long\n");
  238. printf("#define ALGN .align 4\n");
  239. printf("#endif\n");
  240.  
  241. printf(".data\n");
  242.  
  243. /* Provide proper symbols relocatability by their '_text'
  244. * relativeness. The symbol names cannot be used to construct
  245. * normal symbol references as the list of symbols contains
  246. * symbols that are declared static and are private to their
  247. * .o files. This prevents .tmp_kallsyms.o or any other
  248. * object from referencing them.
  249. */
  250. output_label("kallsyms_addresses");
  251. for (i = 0; i < table_cnt; i++) {
  252. if (toupper(table[i].sym[0]) != 'A') {
  253. printf("\tPTR\t_text + %#llx\n",
  254. table[i].addr - _text);
  255. } else {
  256. printf("\tPTR\t%#llx\n", table[i].addr);
  257. }
  258. }
  259. printf("\n");
  260.  
  261. output_label("kallsyms_num_syms");
  262. printf("\tPTR\t%d\n", table_cnt);
  263. printf("\n");
  264.  
  265. /* table of offset markers, that give the offset in the compressed stream
  266. * every 256 symbols */
  267. markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
  268. if (!markers) {
  269. fprintf(stderr, "kallsyms failure: "
  270. "unable to allocate required memory\n");
  271. exit(EXIT_FAILURE);
  272. }
  273.  
  274. output_label("kallsyms_names");
  275. off = 0;
  276. for (i = 0; i < table_cnt; i++) {
  277. if ((i & 0xFF) == 0)
  278. markers[i >> 8] = off;
  279.  
  280. printf("\t.byte 0x%02x", table[i].len);
  281. for (k = 0; k < table[i].len; k++)
  282. printf(", 0x%02x", table[i].sym[k]);
  283. printf("\n");
  284.  
  285. off += table[i].len + 1;
  286. }
  287. printf("\n");
  288.  
  289. output_label("kallsyms_markers");
  290. for (i = 0; i < ((table_cnt + 255) >> 8); i++)
  291. printf("\tPTR\t%d\n", markers[i]);
  292. printf("\n");
  293.  
  294. free(markers);
  295.  
  296. output_label("kallsyms_token_table");
  297. off = 0;
  298. for (i = 0; i < 256; i++) {
  299. best_idx[i] = off;
  300. expand_symbol(best_table[i], best_table_len[i], buf);
  301. printf("\t.asciz\t\"%s\"\n", buf);
  302. off += strlen(buf) + 1;
  303. }
  304. printf("\n");
  305.  
  306. output_label("kallsyms_token_index");
  307. for (i = 0; i < 256; i++)
  308. printf("\t.short\t%d\n", best_idx[i]);
  309. printf("\n");
  310. }
  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 < 0x10000; 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 '\0' 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.  
  470. int main(int argc, char **argv)
  471. {
  472. if (argc >= 2) {
  473. int i;
  474. for (i = 1; i < argc; i++) {
  475. if(strcmp(argv[i], "--all-symbols") == 0)
  476. all_symbols = 1;
  477. else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) {
  478. char *p = &argv[i][16];
  479. /* skip quote */
  480. if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
  481. p++;
  482. symbol_prefix_char = *p;
  483. } else
  484. usage();
  485. }
  486. } else if (argc != 1)
  487. usage();
  488.  
  489. read_map(stdin);
  490. optimize_token_table();
  491. write_src();
  492.  
  493. return 0;
  494. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement