Commit ce57f2a0 authored by Russell King's avatar Russell King Committed by Sam Ravnborg

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: default avatarRussell King <rmk@arm.linux.org.uk>
Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>

===== kernel/module.c 1.120 vs edited =====
parent 44bdb454
......@@ -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;
}
......
......@@ -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
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment