X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=scripts%2Fkallsyms.c;h=86c3896a1e01862b222adeaac4e33bc9b8a01aad;hb=99cf611613f8826f52c156810bfb9e34c71d193a;hp=ad2434b26970c17b4b72efb82761afd0ac04042d;hpb=2ea038917bbdd51a7ae4a898c6a04641324dd033;p=safe%2Fjmp%2Flinux-2.6 diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index ad2434b..86c3896 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -23,6 +23,10 @@ #include #include +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) +#endif + #define KSYM_NAME_LEN 128 struct sym_entry { @@ -32,9 +36,23 @@ struct sym_entry { unsigned char *sym; }; +struct text_range { + const char *stext, *etext; + unsigned long long start, end; +}; + +static unsigned long long _text; +static struct text_range text_ranges[] = { + { "_stext", "_etext" }, + { "_sinittext", "_einittext" }, + { "_stext_l1", "_etext_l1" }, /* Blackfin on-chip L1 inst SRAM */ + { "_stext_l2", "_etext_l2" }, /* Blackfin on-chip L2 SRAM */ +}; +#define text_range_text (&text_ranges[0]) +#define text_range_inittext (&text_ranges[1]) + static struct sym_entry *table; static unsigned int table_size, table_cnt; -static unsigned long long _text, _stext, _etext, _sinittext, _einittext; static int all_symbols = 0; static char symbol_prefix_char = '\0'; @@ -61,6 +79,26 @@ 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) +{ + size_t i; + struct text_range *tr; + + for (i = 0; i < ARRAY_SIZE(text_ranges); ++i) { + tr = &text_ranges[i]; + + if (strcmp(sym, tr->stext) == 0) { + tr->start = addr; + return 0; + } else if (strcmp(sym, tr->etext) == 0) { + tr->end = addr; + return 0; + } + } + + return 1; +} + static int read_symbol(FILE *in, struct sym_entry *s) { char str[500]; @@ -84,14 +122,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 (strcmp(sym, "_stext") == 0) - _stext = s->addr; - else if (strcmp(sym, "_etext") == 0) - _etext = s->addr; - else if (strcmp(sym, "_sinittext") == 0) - _sinittext = s->addr; - else if (strcmp(sym, "_einittext") == 0) - _einittext = s->addr; + else if (read_symbol_tr(sym, s->addr) == 0) + /* nothing to do */; else if (toupper(stype) == 'A') { /* Keep these useful absolute symbols */ @@ -127,6 +159,21 @@ static int read_symbol(FILE *in, struct sym_entry *s) return 0; } +static int symbol_valid_tr(struct sym_entry *s) +{ + size_t i; + struct text_range *tr; + + for (i = 0; i < ARRAY_SIZE(text_ranges); ++i) { + tr = &text_ranges[i]; + + if (s->addr >= tr->start && s->addr <= tr->end) + return 1; + } + + return 0; +} + static int symbol_valid(struct sym_entry *s) { /* Symbols which vary between passes. Passes 1 and 2 must have @@ -156,8 +203,7 @@ 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 ((s->addr < _stext || s->addr > _etext) - && (s->addr < _sinittext || s->addr > _einittext)) + if (symbol_valid_tr(s) == 0) return 0; /* Corner case. Discard any symbols with the same value as * _etext _einittext; they can move between pass 1 and 2 when @@ -165,10 +211,10 @@ static int symbol_valid(struct sym_entry *s) * they may get dropped in pass 2, which breaks the kallsyms * rules. */ - if ((s->addr == _etext && - strcmp((char *)s->sym + offset, "_etext")) || - (s->addr == _einittext && - strcmp((char *)s->sym + offset, "_einittext"))) + if ((s->addr == text_range_text->end && + strcmp((char *)s->sym + offset, text_range_text->etext)) || + (s->addr == text_range_inittext->end && + strcmp((char *)s->sym + offset, text_range_inittext->etext))) return 0; } @@ -500,6 +546,51 @@ static void optimize_token_table(void) optimize_result(); } +/* guess for "linker script provide" symbol */ +static int may_be_linker_script_provide_symbol(const struct sym_entry *se) +{ + const char *symbol = (char *)se->sym + 1; + int len = se->len - 1; + + if (len < 8) + return 0; + + if (symbol[0] != '_' || symbol[1] != '_') + return 0; + + /* __start_XXXXX */ + if (!memcmp(symbol + 2, "start_", 6)) + return 1; + + /* __stop_XXXXX */ + if (!memcmp(symbol + 2, "stop_", 5)) + return 1; + + /* __end_XXXXX */ + if (!memcmp(symbol + 2, "end_", 4)) + return 1; + + /* __XXXXX_start */ + if (!memcmp(symbol + len - 6, "_start", 6)) + return 1; + + /* __XXXXX_end */ + if (!memcmp(symbol + len - 4, "_end", 4)) + return 1; + + return 0; +} + +static int prefix_underscores_count(const char *str) +{ + const char *tail = str; + + while (*tail == '_') + tail++; + + return tail - str; +} + static int compare_symbols(const void *a, const void *b) { const struct sym_entry *sa; @@ -521,6 +612,18 @@ static int compare_symbols(const void *a, const void *b) if (wa != wb) return wa - wb; + /* sort by "linker script provide" type */ + wa = may_be_linker_script_provide_symbol(sa); + wb = may_be_linker_script_provide_symbol(sb); + if (wa != wb) + return wa - wb; + + /* sort by the number of prefix underscores */ + wa = prefix_underscores_count((const char *)sa->sym + 1); + wb = prefix_underscores_count((const char *)sb->sym + 1); + if (wa != wb) + return wa - wb; + /* sort by initial order, so that other symbols are left undisturbed */ return sa->start_pos - sb->start_pos; }