diff options
Diffstat (limited to 'scripts/kallsyms.c')
| -rw-r--r-- | scripts/kallsyms.c | 94 |
1 files changed, 72 insertions, 22 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 60dd3eb9366..dc7aa45e80c 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -36,13 +36,13 @@ struct sym_entry { unsigned char *sym; }; -struct text_range { - const char *stext, *etext; +struct addr_range { + const char *start_sym, *end_sym; unsigned long long start, end; }; static unsigned long long _text; -static struct text_range text_ranges[] = { +static struct addr_range text_ranges[] = { { "_stext", "_etext" }, { "_sinittext", "_einittext" }, { "_stext_l1", "_etext_l1" }, /* Blackfin on-chip L1 inst SRAM */ @@ -51,10 +51,16 @@ static struct text_range text_ranges[] = { #define text_range_text (&text_ranges[0]) #define text_range_inittext (&text_ranges[1]) +static struct addr_range percpu_range = { + "__per_cpu_start", "__per_cpu_end", -1ULL, 0 +}; + static struct sym_entry *table; static unsigned int table_size, table_cnt; static int all_symbols = 0; +static int absolute_percpu = 0; static char symbol_prefix_char = '\0'; +static unsigned long long kernel_start_addr = 0; int token_profit[0x10000]; @@ -65,7 +71,10 @@ unsigned char best_table_len[256]; static void usage(void) { - fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n"); + fprintf(stderr, "Usage: kallsyms [--all-symbols] " + "[--symbol-prefix=<prefix char>] " + "[--page-offset=<CONFIG_PAGE_OFFSET>] " + "< in.map > out.S\n"); exit(1); } @@ -79,19 +88,20 @@ static inline int is_arm_mapping_symbol(const char *str) && (str[2] == '\0' || str[2] == '.'); } -static int read_symbol_tr(const char *sym, unsigned long long addr) +static int check_symbol_range(const char *sym, unsigned long long addr, + struct addr_range *ranges, int entries) { size_t i; - struct text_range *tr; + struct addr_range *ar; - for (i = 0; i < ARRAY_SIZE(text_ranges); ++i) { - tr = &text_ranges[i]; + for (i = 0; i < entries; ++i) { + ar = &ranges[i]; - if (strcmp(sym, tr->stext) == 0) { - tr->start = addr; + if (strcmp(sym, ar->start_sym) == 0) { + ar->start = addr; return 0; - } else if (strcmp(sym, tr->etext) == 0) { - tr->end = addr; + } else if (strcmp(sym, ar->end_sym) == 0) { + ar->end = addr; return 0; } } @@ -111,6 +121,12 @@ static int read_symbol(FILE *in, struct sym_entry *s) fprintf(stderr, "Read error or end of file.\n"); return -1; } + if (strlen(str) > KSYM_NAME_LEN) { + fprintf(stderr, "Symbol %s too long for kallsyms (%zu vs %d).\n" + "Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n", + str, strlen(str), KSYM_NAME_LEN); + return -1; + } sym = str; /* skip prefix char */ @@ -120,7 +136,8 @@ static int read_symbol(FILE *in, struct sym_entry *s) /* Ignore most absolute/undefined (?) symbols. */ if (strcmp(sym, "_text") == 0) _text = s->addr; - else if (read_symbol_tr(sym, s->addr) == 0) + else if (check_symbol_range(sym, s->addr, text_ranges, + ARRAY_SIZE(text_ranges)) == 0) /* nothing to do */; else if (toupper(stype) == 'A') { @@ -154,18 +171,22 @@ static int read_symbol(FILE *in, struct sym_entry *s) strcpy((char *)s->sym + 1, str); s->sym[0] = stype; + /* Record if we've found __per_cpu_start/end. */ + check_symbol_range(sym, s->addr, &percpu_range, 1); + return 0; } -static int symbol_valid_tr(struct sym_entry *s) +static int symbol_in_range(struct sym_entry *s, struct addr_range *ranges, + int entries) { size_t i; - struct text_range *tr; + struct addr_range *ar; - for (i = 0; i < ARRAY_SIZE(text_ranges); ++i) { - tr = &text_ranges[i]; + for (i = 0; i < entries; ++i) { + ar = &ranges[i]; - if (s->addr >= tr->start && s->addr <= tr->end) + if (s->addr >= ar->start && s->addr <= ar->end) return 1; } @@ -194,6 +215,9 @@ static int symbol_valid(struct sym_entry *s) int i; int offset = 1; + if (s->addr < kernel_start_addr) + return 0; + /* skip prefix char */ if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char) offset++; @@ -201,7 +225,8 @@ static int symbol_valid(struct sym_entry *s) /* if --all-symbols is not specified, then symbols outside the text * and inittext sections are discarded */ if (!all_symbols) { - if (symbol_valid_tr(s) == 0) + if (symbol_in_range(s, text_ranges, + ARRAY_SIZE(text_ranges)) == 0) return 0; /* Corner case. Discard any symbols with the same value as * _etext _einittext; they can move between pass 1 and 2 when @@ -210,9 +235,11 @@ static int symbol_valid(struct sym_entry *s) * rules. */ if ((s->addr == text_range_text->end && - strcmp((char *)s->sym + offset, text_range_text->etext)) || + strcmp((char *)s->sym + offset, + text_range_text->end_sym)) || (s->addr == text_range_inittext->end && - strcmp((char *)s->sym + offset, text_range_inittext->etext))) + strcmp((char *)s->sym + offset, + text_range_inittext->end_sym))) return 0; } @@ -285,6 +312,11 @@ static int expand_symbol(unsigned char *data, int len, char *result) return total; } +static int symbol_absolute(struct sym_entry *s) +{ + return toupper(s->sym[0]) == 'A'; +} + static void write_src(void) { unsigned int i, k, off; @@ -312,7 +344,7 @@ static void write_src(void) */ output_label("kallsyms_addresses"); for (i = 0; i < table_cnt; i++) { - if (toupper(table[i].sym[0]) != 'A') { + if (!symbol_absolute(&table[i])) { if (_text <= table[i].addr) printf("\tPTR\t_text + %#llx\n", table[i].addr - _text); @@ -500,6 +532,8 @@ static void optimize_result(void) /* find the token with the breates profit value */ best = find_best_token(); + if (token_profit[best] == 0) + break; /* place it in the "best" table */ best_table_len[i] = 2; @@ -631,6 +665,15 @@ static void sort_symbols(void) qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols); } +static void make_percpus_absolute(void) +{ + unsigned int i; + + for (i = 0; i < table_cnt; i++) + if (symbol_in_range(&table[i], &percpu_range, 1)) + table[i].sym[0] = 'A'; +} + int main(int argc, char **argv) { if (argc >= 2) { @@ -638,12 +681,17 @@ int main(int argc, char **argv) for (i = 1; i < argc; i++) { if(strcmp(argv[i], "--all-symbols") == 0) all_symbols = 1; + else if (strcmp(argv[i], "--absolute-percpu") == 0) + absolute_percpu = 1; else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) { char *p = &argv[i][16]; /* skip quote */ if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\'')) p++; symbol_prefix_char = *p; + } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { + const char *p = &argv[i][14]; + kernel_start_addr = strtoull(p, NULL, 16); } else usage(); } @@ -651,6 +699,8 @@ int main(int argc, char **argv) usage(); read_map(stdin); + if (absolute_percpu) + make_percpus_absolute(); sort_symbols(); optimize_token_table(); write_src(); |
