--- zzzz-none-000/linux-3.10.107/scripts/kallsyms.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/scripts/kallsyms.c 2021-02-04 17:41:59.000000000 +0000 @@ -22,6 +22,35 @@ #include #include #include +#ifdef __APPLE__ +/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */ +void *memmem (const void *haystack, size_t haystack_len, + const void *needle, size_t needle_len) +{ + const char *begin; + const char *const last_possible + = (const char *) haystack + haystack_len - needle_len; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + for (begin = (const char *) haystack; begin <= last_possible; ++begin) + if (begin[0] == ((const char *) needle)[0] && + !memcmp ((const void *) &begin[1], + (const void *) ((const char *) needle + 1), + needle_len - 1)) + return (void *) begin; + + return NULL; +} +#endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) @@ -36,13 +65,13 @@ 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,9 +80,15 @@ #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 uncompressed = 0; +static int absolute_percpu = 0; static char symbol_prefix_char = '\0'; static unsigned long long kernel_start_addr = 0; @@ -79,23 +114,24 @@ */ static inline int is_arm_mapping_symbol(const char *str) { - return str[0] == '$' && strchr("atd", str[1]) + return str[0] == '$' && strchr("axtd", str[1]) && (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; } } @@ -115,6 +151,12 @@ 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 */ @@ -124,7 +166,8 @@ /* 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') { @@ -158,18 +201,22 @@ 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; } @@ -195,20 +242,28 @@ "_SDA_BASE_", /* ppc */ "_SDA2_BASE_", /* ppc */ NULL }; + + static char *special_suffixes[] = { + "_veneer", /* arm */ + NULL }; + int i; - int offset = 1; + char *sym_name = (char *)s->sym + 1; + if (s->addr < kernel_start_addr) return 0; /* skip prefix char */ - if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char) - offset++; + if (symbol_prefix_char && *sym_name == symbol_prefix_char) + sym_name++; + /* 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 @@ -217,20 +272,26 @@ * rules. */ if ((s->addr == text_range_text->end && - strcmp((char *)s->sym + offset, text_range_text->etext)) || + strcmp(sym_name, + text_range_text->end_sym)) || (s->addr == text_range_inittext->end && - strcmp((char *)s->sym + offset, text_range_inittext->etext))) + strcmp(sym_name, + text_range_inittext->end_sym))) return 0; } /* Exclude symbols which vary between passes. */ - if (strstr((char *)s->sym + offset, "_compiled.")) - return 0; - for (i = 0; special_symbols[i]; i++) - if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 ) + if (strcmp(sym_name, special_symbols[i]) == 0) return 0; + for (i = 0; special_suffixes[i]; i++) { + int l = strlen(sym_name) - strlen(special_suffixes[i]); + + if (l >= 0 && strcmp(sym_name + l, special_suffixes[i]) == 0) + return 0; + } + return 1; } @@ -292,6 +353,11 @@ 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; @@ -319,7 +385,7 @@ */ 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); @@ -367,6 +433,9 @@ free(markers); + if (uncompressed) + return; + output_label("kallsyms_token_table"); off = 0; for (i = 0; i < 256; i++) { @@ -425,6 +494,9 @@ { int i; + if (uncompressed) + return NULL; + for (i = 0; i < len - 1; i++) { if (str[i] == token[0] && str[i+1] == token[1]) return &str[i]; @@ -497,6 +569,9 @@ { int i, best; + if (uncompressed) + return; + /* using the '\0' symbol last allows compress_symbols to use standard * fast string functions */ for (i = 255; i >= 0; i--) { @@ -640,6 +715,15 @@ 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) { @@ -647,6 +731,8 @@ 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 */ @@ -656,13 +742,17 @@ } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { const char *p = &argv[i][14]; kernel_start_addr = strtoull(p, NULL, 16); - } else + } else if (strcmp(argv[i], "--uncompressed") == 0) + uncompressed = 1; + else usage(); } } else if (argc != 1) usage(); read_map(stdin); + if (absolute_percpu) + make_percpus_absolute(); sort_symbols(); optimize_token_table(); write_src();