[PATCH] Fix ARM kernel build with permitted binutils versions

Russell King
2004-10-20T11:44:54Z

Ok, here's the latest version of the patch, fixing all presently known
issues with ARM binutils post 2.11.90 by changing the kernel to suit.

Yes, it sounds like the wrong thing to do, but shrug.

---

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>

===== kernel/module.c 1.120 vs edited =====
--- 1.120/kernel/module.c 2004-09-08 07:33:04 +01:00
+++ edited/kernel/module.c 2004-10-08 16:34:19 +01:00
@@ -1903,6 +1903,16 @@
}

#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,
@@ -1927,11 +1937,13 @@
* 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;
}

===== scripts/kallsyms.c 1.12 vs edited =====
--- 1.12/scripts/kallsyms.c 2004-07-11 10:23:27 +01:00
+++ edited/scripts/kallsyms.c 2004-10-08 16:34:20 +01:00
@@ -32,6 +32,17 @@
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)
{
@@ -56,7 +67,8 @@
_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;

s->sym = strdup(str);
===== scripts/mksysmap 1.4 vs edited =====
--- 1.4/scripts/mksysmap 2004-08-18 22:05:12 +01:00
+++ edited/scripts/mksysmap 2004-10-08 16:39:39 +01:00
@@ -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

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/
2.6 Serial core