xfs: use memdup_user()
[safe/jmp/linux-2.6] / scripts / kallsyms.c
index c912137..6654cbe 100644 (file)
@@ -7,12 +7,6 @@
  *
  * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
  *
- * ChangeLog:
- *
- * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
- *      Changed the compression method from stem compression to "table lookup"
- *      compression
- *
  *      Table compression uses all the unused char codes on the symbols and
  *  maps these to the most used substrings (tokens). For instance, it might
  *  map char code 0xF7 to represent "write_" and then in every symbol where
@@ -114,6 +108,9 @@ static int read_symbol(FILE *in, struct sym_entry *s)
        /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */
        else if (str[0] == '$')
                return -1;
+       /* exclude debugging symbols */
+       else if (stype == 'N')
+               return -1;
 
        /* include the type field in the symbol name, so that it gets
         * compressed together */
@@ -503,6 +500,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;
@@ -524,6 +566,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;
 }