Re: inconsistent kallsyms data [2.6.11-mm2]

From: Paulo Marques
Date: Thu Mar 10 2005 - 07:18:10 EST


Paulo Marques wrote:
[...]
A simple and robust way is to do the sampling on a list of symbols sorted by symbol name. This way, even if the symbol positions that are given to scripts/kallsyms change, the symbols sampled will be the same.

I'll do the patch to do this and send it ASAP.

Ok, here it is.

Dominik can you try the attached patch and see if it solves the problem?

It it does, I'll do a correct [PATCH] post later with all the signed-off-by and subject and stuff.

Please make sure you test with the same configuration that produces the error, because this is a pretty hard to hit bug. The needed conditions are:

- 'nm' changes the order of 2 aliased symbols from the 1st to the 2nd pass
- one of those symbols get sampled for token optimization. With your configuration the sampling was about 1 out of 12.
- the difference in the name of those symbols makes the algorithm select different tokens. As 1024 symbols are used to produce the tokens, changing just one of these symbols can easily go unnoticed.
- the difference in the tokens selected makes the size of the compressed data change, so that it goes above (or below) an alignment boundary. In your case it only changed 2 bytes in size, but it crossed a 4 byte alignment boundary.

With your .config file but a different set of tools (gcc, binutils versions) I couldn't trigger the bug in my machine.

--
Paulo Marques - www.grupopie.com

All that is necessary for the triumph of evil is that good men do nothing.
Edmund Burke (1729 - 1797)
--- ./scripts/kallsyms.c.orig 2005-03-10 11:00:26.000000000 +0000
+++ ./scripts/kallsyms.c 2005-03-10 11:11:50.000000000 +0000
@@ -499,11 +499,30 @@ static void forget_symbol(unsigned char
forget_token(symbol + i, len - i);
}

+/* sort the symbols by address->name so that even if aliased symbols
+ * change position, or the symbols are not supplied in address order
+ * the algorithm will work nevertheless */
+
+static int sort_by_address_name(const void *a, const void *b)
+{
+ struct sym_entry *sa, *sb;
+
+ sa = (struct sym_entry *) a;
+ sb = (struct sym_entry *) b;
+
+ if (sa->addr != sb->addr)
+ return sa->addr - sb->addr;
+
+ return strcmp(sa->sym + 1, sb->sym + 1);
+}
+
/* set all the symbol flags and do the initial token count */
static void build_initial_tok_table(void)
{
int i, use_it, valid;

+ qsort(table, cnt, sizeof(table[0]), sort_by_address_name);
+
valid = 0;
for (i = 0; i < cnt; i++) {
table[i].flags = 0;