]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - scripts/kallsyms.c
scripts/kallsyms: replace prefix_underscores_count() with strspn()
[linux.git] / scripts / kallsyms.c
index ae6504d07fd6123b6a9d984bec070ece4c59d613..89cc7c098c5187326f17d639ea10183d8c0f3da0 100644 (file)
@@ -24,9 +24,7 @@
 #include <ctype.h>
 #include <limits.h>
 
-#ifndef ARRAY_SIZE
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
-#endif
 
 #define KSYM_NAME_LEN          128
 
@@ -76,14 +74,9 @@ static void usage(void)
        exit(1);
 }
 
-/*
- * This ignores the intensely annoying "mapping symbols" found
- * in ARM ELF files: $a, $t and $d.
- */
-static int is_arm_mapping_symbol(const char *str)
+static char *sym_name(const struct sym_entry *s)
 {
-       return str[0] == '$' && strchr("axtd", str[1])
-              && (str[2] == '\0' || str[2] == '.');
+       return (char *)s->sym + 1;
 }
 
 static int check_symbol_range(const char *sym, unsigned long long addr,
@@ -141,10 +134,13 @@ static int read_symbol(FILE *in, struct sym_entry *s)
                        return -1;
 
        }
-       else if (toupper(stype) == 'U' ||
-                is_arm_mapping_symbol(sym))
+       else if (toupper(stype) == 'U')
                return -1;
-       /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
+       /*
+        * Ignore generated symbols such as:
+        *  - mapping symbols in ARM ELF files ($a, $t, and $d)
+        *  - MIPS ELF local symbols ($L123 instead of .L123)
+        */
        else if (sym[0] == '$')
                return -1;
        /* exclude debugging symbols */
@@ -163,7 +159,7 @@ static int read_symbol(FILE *in, struct sym_entry *s)
                        "unable to allocate required amount of memory\n");
                exit(EXIT_FAILURE);
        }
-       strcpy((char *)s->sym + 1, sym);
+       strcpy(sym_name(s), sym);
        s->sym[0] = stype;
 
        s->percpu_absolute = 0;
@@ -224,7 +220,7 @@ static int symbol_valid(struct sym_entry *s)
                NULL };
 
        int i;
-       char *sym_name = (char *)s->sym + 1;
+       const char *name = sym_name(s);
 
        /* if --all-symbols is not specified, then symbols outside the text
         * and inittext sections are discarded */
@@ -239,37 +235,58 @@ static int symbol_valid(struct sym_entry *s)
                 * rules.
                 */
                if ((s->addr == text_range_text->end &&
-                               strcmp(sym_name,
-                                      text_range_text->end_sym)) ||
+                    strcmp(name, text_range_text->end_sym)) ||
                    (s->addr == text_range_inittext->end &&
-                               strcmp(sym_name,
-                                      text_range_inittext->end_sym)))
+                    strcmp(name, text_range_inittext->end_sym)))
                        return 0;
        }
 
        /* Exclude symbols which vary between passes. */
        for (i = 0; special_symbols[i]; i++)
-               if (strcmp(sym_name, special_symbols[i]) == 0)
+               if (strcmp(name, special_symbols[i]) == 0)
                        return 0;
 
        for (i = 0; special_prefixes[i]; i++) {
                int l = strlen(special_prefixes[i]);
 
-               if (l <= strlen(sym_name) &&
-                   strncmp(sym_name, special_prefixes[i], l) == 0)
+               if (strncmp(name, special_prefixes[i], l) == 0)
                        return 0;
        }
 
        for (i = 0; special_suffixes[i]; i++) {
-               int l = strlen(sym_name) - strlen(special_suffixes[i]);
+               int l = strlen(name) - strlen(special_suffixes[i]);
 
-               if (l >= 0 && strcmp(sym_name + l, special_suffixes[i]) == 0)
+               if (l >= 0 && strcmp(name + l, special_suffixes[i]) == 0)
                        return 0;
        }
 
        return 1;
 }
 
+/* remove all the invalid symbols from the table */
+static void shrink_table(void)
+{
+       unsigned int i, pos;
+
+       pos = 0;
+       for (i = 0; i < table_cnt; i++) {
+               if (symbol_valid(&table[i])) {
+                       if (pos != i)
+                               table[pos] = table[i];
+                       pos++;
+               } else {
+                       free(table[i].sym);
+               }
+       }
+       table_cnt = pos;
+
+       /* When valid symbol is not registered, exit to error */
+       if (!table_cnt) {
+               fprintf(stderr, "No valid symbol.\n");
+               exit(1);
+       }
+}
+
 static void read_map(FILE *in)
 {
        while (!feof(in)) {
@@ -477,21 +494,13 @@ static void forget_symbol(unsigned char *symbol, int len)
                token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
 }
 
-/* remove all the invalid symbols from the table and do the initial token count */
+/* do the initial token count */
 static void build_initial_tok_table(void)
 {
-       unsigned int i, pos;
+       unsigned int i;
 
-       pos = 0;
-       for (i = 0; i < table_cnt; i++) {
-               if ( symbol_valid(&table[i]) ) {
-                       if (pos != i)
-                               table[pos] = table[i];
-                       learn_symbol(table[pos].sym, table[pos].len);
-                       pos++;
-               }
-       }
-       table_cnt = pos;
+       for (i = 0; i < table_cnt; i++)
+               learn_symbol(table[i].sym, table[i].len);
 }
 
 static void *find_token(unsigned char *str, int len, unsigned char *token)
@@ -614,19 +623,13 @@ static void optimize_token_table(void)
 
        insert_real_symbols_in_table();
 
-       /* When valid symbol is not registered, exit to error */
-       if (!table_cnt) {
-               fprintf(stderr, "No valid symbol.\n");
-               exit(1);
-       }
-
        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;
+       const char *symbol = sym_name(se);
        int len = se->len - 1;
 
        if (len < 8)
@@ -658,16 +661,6 @@ static int may_be_linker_script_provide_symbol(const struct sym_entry *se)
        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;
@@ -696,8 +689,8 @@ static int compare_symbols(const void *a, const void *b)
                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);
+       wa = strspn(sym_name(sa), "_");
+       wb = strspn(sym_name(sb), "_");
        if (wa != wb)
                return wa - wb;
 
@@ -731,11 +724,15 @@ static void record_relative_base(void)
 {
        unsigned int i;
 
-       relative_base = -1ULL;
        for (i = 0; i < table_cnt; i++)
-               if (!symbol_absolute(&table[i]) &&
-                   table[i].addr < relative_base)
+               if (!symbol_absolute(&table[i])) {
+                       /*
+                        * The table is sorted by address.
+                        * Take the first non-absolute symbol value.
+                        */
                        relative_base = table[i].addr;
+                       return;
+               }
 }
 
 int main(int argc, char **argv)
@@ -756,11 +753,12 @@ int main(int argc, char **argv)
                usage();
 
        read_map(stdin);
+       shrink_table();
        if (absolute_percpu)
                make_percpus_absolute();
+       sort_symbols();
        if (base_relative)
                record_relative_base();
-       sort_symbols();
        optimize_token_table();
        write_src();