浏览代码

Kbuild: kallsyms: ignore veneers emitted by the ARM linker

When linking large kernels on ARM, the linker will insert veneers
(i.e., PLT like stubs) when function symbols are out of reach for
the ordinary relative branch/branch-and-link instructions.

However, due to the fact that the kallsyms region sits in .rodata,
which is between .text and .init.text, additional veneers may be
emitted in the second pass due to the fact that the size of the
kallsyms region itself has pushed the .init.text section further
apart, requiring even more veneers.

So ignore the veneers when generating the symbol table. Veneers
have no corresponding source code, and they will not turn up in
backtraces anyway.

This patch also lightly refactors the symbol_valid() function
to use a local 'sym_name' rather than the obfuscated 'sym + 1'
and 'sym + offset'

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Michal Marek <mmarek@suse.cz>
Ard Biesheuvel 10 年之前
父节点
当前提交
bd8b22d288
共有 1 个文件被更改,包括 21 次插入9 次删除
  1. 21 9
      scripts/kallsyms.c

+ 21 - 9
scripts/kallsyms.c

@@ -212,15 +212,23 @@ static int symbol_valid(struct sym_entry *s)
 		"_SDA_BASE_",		/* ppc */
 		"_SDA_BASE_",		/* ppc */
 		"_SDA2_BASE_",		/* ppc */
 		"_SDA2_BASE_",		/* ppc */
 		NULL };
 		NULL };
+
+	static char *special_suffixes[] = {
+		"_compiled.",		/* gcc < 3.0: "gcc[0-9]_compiled." */
+		"_veneer",		/* arm */
+		NULL };
+
 	int i;
 	int i;
-	int offset = 1;
+	char *sym_name = (char *)s->sym + 1;
+
 
 
 	if (s->addr < kernel_start_addr)
 	if (s->addr < kernel_start_addr)
 		return 0;
 		return 0;
 
 
 	/* skip prefix char */
 	/* skip prefix char */
-	if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
-		offset++;
+	if (symbol_prefix_char && *sym_name == symbol_prefix_char)
+		sym_name++;
+
 
 
 	/* if --all-symbols is not specified, then symbols outside the text
 	/* if --all-symbols is not specified, then symbols outside the text
 	 * and inittext sections are discarded */
 	 * and inittext sections are discarded */
@@ -235,22 +243,26 @@ static int symbol_valid(struct sym_entry *s)
 		 * rules.
 		 * rules.
 		 */
 		 */
 		if ((s->addr == text_range_text->end &&
 		if ((s->addr == text_range_text->end &&
-				strcmp((char *)s->sym + offset,
+				strcmp(sym_name,
 				       text_range_text->end_sym)) ||
 				       text_range_text->end_sym)) ||
 		    (s->addr == text_range_inittext->end &&
 		    (s->addr == text_range_inittext->end &&
-				strcmp((char *)s->sym + offset,
+				strcmp(sym_name,
 				       text_range_inittext->end_sym)))
 				       text_range_inittext->end_sym)))
 			return 0;
 			return 0;
 	}
 	}
 
 
 	/* Exclude symbols which vary between passes. */
 	/* Exclude symbols which vary between passes. */
-	if (strstr((char *)s->sym + offset, "_compiled."))
-		return 0;
-
 	for (i = 0; special_symbols[i]; i++)
 	for (i = 0; special_symbols[i]; i++)
-		if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 )
+		if (strcmp(sym_name, special_symbols[i]) == 0)
 			return 0;
 			return 0;
 
 
+	for (i = 0; special_suffixes[i]; i++) {
+		int l = strlen(sym_name) - strlen(special_suffixes[i]);
+
+		if (l >= 0 && strcmp(sym_name + l, special_suffixes[i]) == 0)
+			return 0;
+	}
+
 	return 1;
 	return 1;
 }
 }