diff options
| author | Russell King <rmk+lkml@arm.linux.org.uk> | 2004-10-27 04:36:12 +0200 |
|---|---|---|
| committer | Sam Ravnborg <sam@mars.ravnborg.org> | 2004-10-27 04:36:12 +0200 |
| commit | ce57f2a048bcf2c755b37944e397bdb71202ec77 (patch) | |
| tree | cc7c84a7903490887b1d5156e86337331e2d590a | |
| parent | 44bdb454541a769c55fbb043b9305b069822e2fd (diff) | |
arm: Fix ARM kernel build with permitted binutils versions
All ARM binutils versions post 2.11.90 contains an extra "feature" which
interferes with the kernel in various ways - extra "mapping symbols"
in the ELF symbol table '$a', '$t' and '$d'. This causes two problems:
1. Since '$a' symbols have the same value as function names, this
causes anything which uses the kallsyms infrastructure to report
wrong values.
2. programs which parse System.map do not expect symbols to start with
'$'.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
===== kernel/module.c 1.120 vs edited =====
| -rw-r--r-- | kernel/module.c | 16 | ||||
| -rw-r--r-- | scripts/kallsyms.c | 14 | ||||
| -rw-r--r-- | scripts/mksysmap | 2 |
3 files changed, 28 insertions, 4 deletions
diff --git a/kernel/module.c b/kernel/module.c index c6e8e922dc63..f58f5e168624 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1834,6 +1834,16 @@ static inline int within(unsigned long addr, void *start, unsigned long size) } #ifdef CONFIG_KALLSYMS +/* + * This ignores the intensely annoying "mapping symbols" found + * in ARM ELF files: $a, $t and $d. + */ +static inline int is_arm_mapping_symbol(const char *str) +{ + return str[0] == '$' && strchr("atd", str[1]) + && (str[2] == '\0' || str[2] == '.'); +} + static const char *get_ksymbol(struct module *mod, unsigned long addr, unsigned long *size, @@ -1858,11 +1868,13 @@ static const char *get_ksymbol(struct module *mod, * and inserted at a whim. */ if (mod->symtab[i].st_value <= addr && mod->symtab[i].st_value > mod->symtab[best].st_value - && *(mod->strtab + mod->symtab[i].st_name) != '\0' ) + && *(mod->strtab + mod->symtab[i].st_name) != '\0' + && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name)) best = i; if (mod->symtab[i].st_value > addr && mod->symtab[i].st_value < nextval - && *(mod->strtab + mod->symtab[i].st_name) != '\0') + && *(mod->strtab + mod->symtab[i].st_name) != '\0' + && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name)) nextval = mod->symtab[i].st_value; } diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 2e0e07afb84c..b66b5e47e80c 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -97,6 +97,17 @@ usage(void) exit(1); } +/* + * This ignores the intensely annoying "mapping symbols" found + * in ARM ELF files: $a, $t and $d. + */ +static inline int +is_arm_mapping_symbol(const char *str) +{ + return str[0] == '$' && strchr("atd", str[1]) + && (str[2] == '\0' || str[2] == '.'); +} + static int read_symbol(FILE *in, struct sym_entry *s) { @@ -121,7 +132,8 @@ read_symbol(FILE *in, struct sym_entry *s) _sinittext = s->addr; else if (strcmp(str, "_einittext") == 0) _einittext = s->addr; - else if (toupper(s->type) == 'A' || toupper(s->type) == 'U') + else if (toupper(s->type) == 'A' || toupper(s->type) == 'U' || + is_arm_mapping_symbol(str)) return -1; /* include the type field in the symbol name, so that it gets diff --git a/scripts/mksysmap b/scripts/mksysmap index 2904d3b383ed..a6430e05972d 100644 --- a/scripts/mksysmap +++ b/scripts/mksysmap @@ -40,5 +40,5 @@ # so we just ignore them to let readprofile continue to work. # (At least sparc64 has __crc_ in the middle). -$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)' > $2 +$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)' > $2 |
