aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2015-03-30 09:20:31 -0400
committerMichal Marek <mmarek@suse.cz>2015-04-07 07:04:50 -0400
commitbd8b22d2888e75063c9012b95341d6cb36456434 (patch)
tree4cbbe9fb980626f151b4d92c54b0a11757ea47f0 /scripts
parentd4a4e3f5a3e8bcd8aa778120d5f902b06a0e1019 (diff)
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>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/kallsyms.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index c6d33bd15b04..f4b016782f0d 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -212,15 +212,23 @@ static int symbol_valid(struct sym_entry *s)
212 "_SDA_BASE_", /* ppc */ 212 "_SDA_BASE_", /* ppc */
213 "_SDA2_BASE_", /* ppc */ 213 "_SDA2_BASE_", /* ppc */
214 NULL }; 214 NULL };
215
216 static char *special_suffixes[] = {
217 "_compiled.", /* gcc < 3.0: "gcc[0-9]_compiled." */
218 "_veneer", /* arm */
219 NULL };
220
215 int i; 221 int i;
216 int offset = 1; 222 char *sym_name = (char *)s->sym + 1;
223
217 224
218 if (s->addr < kernel_start_addr) 225 if (s->addr < kernel_start_addr)
219 return 0; 226 return 0;
220 227
221 /* skip prefix char */ 228 /* skip prefix char */
222 if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char) 229 if (symbol_prefix_char && *sym_name == symbol_prefix_char)
223 offset++; 230 sym_name++;
231
224 232
225 /* if --all-symbols is not specified, then symbols outside the text 233 /* if --all-symbols is not specified, then symbols outside the text
226 * and inittext sections are discarded */ 234 * and inittext sections are discarded */
@@ -235,22 +243,26 @@ static int symbol_valid(struct sym_entry *s)
235 * rules. 243 * rules.
236 */ 244 */
237 if ((s->addr == text_range_text->end && 245 if ((s->addr == text_range_text->end &&
238 strcmp((char *)s->sym + offset, 246 strcmp(sym_name,
239 text_range_text->end_sym)) || 247 text_range_text->end_sym)) ||
240 (s->addr == text_range_inittext->end && 248 (s->addr == text_range_inittext->end &&
241 strcmp((char *)s->sym + offset, 249 strcmp(sym_name,
242 text_range_inittext->end_sym))) 250 text_range_inittext->end_sym)))
243 return 0; 251 return 0;
244 } 252 }
245 253
246 /* Exclude symbols which vary between passes. */ 254 /* Exclude symbols which vary between passes. */
247 if (strstr((char *)s->sym + offset, "_compiled."))
248 return 0;
249
250 for (i = 0; special_symbols[i]; i++) 255 for (i = 0; special_symbols[i]; i++)
251 if( strcmp((char *)s->sym + offset, special_symbols[i]) == 0 ) 256 if (strcmp(sym_name, special_symbols[i]) == 0)
252 return 0; 257 return 0;
253 258
259 for (i = 0; special_suffixes[i]; i++) {
260 int l = strlen(sym_name) - strlen(special_suffixes[i]);
261
262 if (l >= 0 && strcmp(sym_name + l, special_suffixes[i]) == 0)
263 return 0;
264 }
265
254 return 1; 266 return 1;
255} 267}
256 268