27 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
30 #define KSYM_NAME_LEN 128
44 static unsigned long long _text;
46 {
"_stext",
"_etext" },
47 {
"_sinittext",
"_einittext" },
48 {
"_stext_l1",
"_etext_l1" },
49 {
"_stext_l2",
"_etext_l2" },
51 #define text_range_text (&text_ranges[0])
52 #define text_range_inittext (&text_ranges[1])
55 static unsigned int table_size, table_cnt;
56 static int all_symbols = 0;
57 static char symbol_prefix_char =
'\0';
66 static void usage(
void)
68 fprintf(stderr,
"Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
76 static inline int is_arm_mapping_symbol(
const char *
str)
78 return str[0] ==
'$' &&
strchr(
"atd", str[1])
79 && (str[2] ==
'\0' || str[2] ==
'.');
82 static int read_symbol_tr(
const char *
sym,
unsigned long long addr)
108 rc = fscanf(in,
"%llx %c %499s\n", &s->
addr, &stype, str);
110 if (rc !=
EOF && fgets(str, 500, in) ==
NULL)
111 fprintf(stderr,
"Read error or end of file.\n");
117 if (symbol_prefix_char && str[0] == symbol_prefix_char)
121 if (
strcmp(sym,
"_text") == 0)
123 else if (read_symbol_tr(sym, s->
addr) == 0)
125 else if (
toupper(stype) ==
'A')
128 if (
strcmp(sym,
"__kernel_syscall_via_break") &&
129 strcmp(sym,
"__kernel_syscall_via_epc") &&
130 strcmp(sym,
"__kernel_sigtramp") &&
135 else if (
toupper(stype) ==
'U' ||
136 is_arm_mapping_symbol(sym))
139 else if (str[0] ==
'$')
142 else if (stype ==
'N')
150 fprintf(stderr,
"kallsyms failure: "
151 "unable to allocate required amount of memory\n");
160 static int symbol_valid_tr(
struct sym_entry *s)
166 tr = &text_ranges[
i];
175 static int symbol_valid(
struct sym_entry *s)
182 static char *special_symbols[] = {
183 "kallsyms_addresses",
187 "kallsyms_token_table",
188 "kallsyms_token_index",
198 if (symbol_prefix_char && *(s->
sym + 1) == symbol_prefix_char)
204 if (symbol_valid_tr(s) == 0)
220 if (
strstr((
char *)s->
sym + offset,
"_compiled."))
223 for (i = 0; special_symbols[
i]; i++)
224 if(
strcmp((
char *)s->
sym + offset, special_symbols[i]) == 0 )
230 static void read_map(FILE *in)
233 if (table_cnt >= table_size) {
235 table = realloc(table,
sizeof(*table) * table_size);
237 fprintf(stderr,
"out of memory\n");
241 if (read_symbol(in, &table[table_cnt]) == 0) {
248 static void output_label(
char *
label)
250 if (symbol_prefix_char)
251 printf(
".globl %c%s\n", symbol_prefix_char, label);
253 printf(
".globl %s\n", label);
255 if (symbol_prefix_char)
256 printf(
"%c%s:\n", symbol_prefix_char, label);
263 static int expand_symbol(
unsigned char *
data,
int len,
char *
result)
265 int c, rlen, total=0;
288 static void write_src(
void)
290 unsigned int i,
k, off;
291 unsigned int best_idx[256];
292 unsigned int *markers;
295 printf(
"#include <asm/types.h>\n");
296 printf(
"#if BITS_PER_LONG == 64\n");
297 printf(
"#define PTR .quad\n");
298 printf(
"#define ALGN .align 8\n");
300 printf(
"#define PTR .long\n");
301 printf(
"#define ALGN .align 4\n");
304 printf(
"\t.section .rodata, \"a\"\n");
313 output_label(
"kallsyms_addresses");
314 for (i = 0; i < table_cnt; i++) {
315 if (
toupper(table[i].sym[0]) !=
'A') {
316 if (_text <= table[i].addr)
317 printf(
"\tPTR\t_text + %#llx\n",
318 table[i].addr - _text);
320 printf(
"\tPTR\t_text - %#llx\n",
321 _text - table[i].addr);
323 printf(
"\tPTR\t%#llx\n", table[i].addr);
328 output_label(
"kallsyms_num_syms");
329 printf(
"\tPTR\t%d\n", table_cnt);
334 markers =
malloc(
sizeof(
unsigned int) * ((table_cnt + 255) / 256));
336 fprintf(stderr,
"kallsyms failure: "
337 "unable to allocate required memory\n");
341 output_label(
"kallsyms_names");
343 for (i = 0; i < table_cnt; i++) {
345 markers[i >> 8] = off;
347 printf(
"\t.byte 0x%02x", table[i].len);
348 for (k = 0; k < table[
i].
len; k++)
349 printf(
", 0x%02x", table[i].sym[k]);
352 off += table[
i].
len + 1;
356 output_label(
"kallsyms_markers");
357 for (i = 0; i < ((table_cnt + 255) >> 8); i++)
358 printf(
"\tPTR\t%d\n", markers[i]);
363 output_label(
"kallsyms_token_table");
365 for (i = 0; i < 256; i++) {
368 printf(
"\t.asciz\t\"%s\"\n", buf);
373 output_label(
"kallsyms_token_index");
374 for (i = 0; i < 256; i++)
375 printf(
"\t.short\t%d\n", best_idx[i]);
383 static void learn_symbol(
unsigned char *
symbol,
int len)
387 for (i = 0; i < len - 1; i++)
392 static void forget_symbol(
unsigned char *symbol,
int len)
396 for (i = 0; i < len - 1; i++)
401 static void build_initial_tok_table(
void)
406 for (i = 0; i < table_cnt; i++) {
407 if ( symbol_valid(&table[i]) ) {
409 table[
pos] = table[
i];
410 learn_symbol(table[pos].sym, table[pos].len);
417 static void *find_token(
unsigned char *str,
int len,
unsigned char *
token)
421 for (i = 0; i < len - 1; i++) {
422 if (str[i] == token[0] && str[i+1] == token[1])
430 static void compress_symbols(
unsigned char *str,
int idx)
432 unsigned int i, len,
size;
433 unsigned char *
p1, *p2;
435 for (i = 0; i < table_cnt; i++) {
441 p2 = find_token(p1, len, str);
445 forget_symbol(table[i].sym, len);
460 p2 = find_token(p1, size, str);
467 learn_symbol(table[i].sym, len);
472 static int find_best_token(
void)
474 int i, best, bestprofit;
479 for (i = 0; i < 0x10000; i++) {
489 static void optimize_result(
void)
495 for (i = 255; i >= 0; i--) {
502 best = find_best_token();
518 static void insert_real_symbols_in_table(
void)
520 unsigned int i,
j,
c;
525 for (i = 0; i < table_cnt; i++) {
526 for (j = 0; j < table[
i].
len; j++) {
534 static void optimize_token_table(
void)
536 build_initial_tok_table();
538 insert_real_symbols_in_table();
542 fprintf(stderr,
"No valid symbol.\n");
550 static int may_be_linker_script_provide_symbol(
const struct sym_entry *se)
552 const char *symbol = (
char *)se->
sym + 1;
553 int len = se->
len - 1;
558 if (symbol[0] !=
'_' || symbol[1] !=
'_')
562 if (!
memcmp(symbol + 2,
"start_", 6))
566 if (!
memcmp(symbol + 2,
"stop_", 5))
570 if (!
memcmp(symbol + 2,
"end_", 4))
574 if (!
memcmp(symbol + len - 6,
"_start", 6))
578 if (!
memcmp(symbol + len - 4,
"_end", 4))
584 static int prefix_underscores_count(
const char *str)
594 static int compare_symbols(
const void *
a,
const void *
b)
610 wa = (sa->
sym[0] ==
'w') || (sa->
sym[0] ==
'W');
611 wb = (sb->
sym[0] ==
'w') || (sb->
sym[0] ==
'W');
616 wa = may_be_linker_script_provide_symbol(sa);
617 wb = may_be_linker_script_provide_symbol(sb);
622 wa = prefix_underscores_count((
const char *)sa->
sym + 1);
623 wb = prefix_underscores_count((
const char *)sb->
sym + 1);
631 static void sort_symbols(
void)
633 qsort(table, table_cnt,
sizeof(
struct sym_entry), compare_symbols);
640 for (i = 1; i <
argc; i++) {
641 if(
strcmp(argv[i],
"--all-symbols") == 0)
643 else if (
strncmp(argv[i],
"--symbol-prefix=", 16) == 0) {
644 char *
p = &argv[
i][16];
646 if ((*p ==
'"' && *(p+2) ==
'"') || (*p ==
'\'' && *(p+2) ==
'\''))
648 symbol_prefix_char = *
p;
652 }
else if (argc != 1)
657 optimize_token_table();