Since commit 5e5c4fa78745 ("scripts/kallsyms: shrink table before sorting it"), kallsyms_relative_base can be larger than _text, which causes overflow when building the 32-bit kernel. https://lkml.org/lkml/2019/12/7/156 This is because _text is, unless --all-symbols is specified, now trimmed from the symbol table before record_relative_base() is called. Handle the offset signedness also for kallsyms_relative_base. Introduce a new helper, output_address(), to reduce the code duplication.
Unified · Split
| @@ -310,6 +310,15 @@ static void output_label(const char *label) · 309 unmodified lines | ||
| 310 | 310 | printf("%s:\n", label); |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | +/* Provide proper symbols relocatability by their '_text' relativeness. */ | |
| 314 | +static void output_address(unsigned long long addr) | |
| 315 | +{ | |
| 316 | + if (_text <= addr) | |
| 317 | + printf("\tPTR\t_text + %#llx\n", addr - _text); | |
| 318 | + else | |
| 319 | + printf("\tPTR\t_text - %#llx\n", _text - addr); | |
| 320 | +} | |
| 321 | + | |
| 313 | 322 | /* uncompress a compressed symbol. When this function is called, the best table |
| 314 | 323 | * might still be compressed itself, so the function needs to be recursive */ |
| 315 | 324 | static int expand_symbol(const unsigned char *data, int len, char *result) |
| @@ -360,19 +369,6 @@ static void write_src(void) · 44 unmodified lines | ||
| 360 | 369 | |
| 361 | 370 | printf("\t.section .rodata, \"a\"\n"); |
| 362 | 371 | |
| 363 | − /* Provide proper symbols relocatability by their relativeness | |
| 364 | − * to a fixed anchor point in the runtime image, either '_text' | |
| 365 | − * for absolute address tables, in which case the linker will | |
| 366 | − * emit the final addresses at build time. Otherwise, use the | |
| 367 | − * offset relative to the lowest value encountered of all relative | |
| 368 | − * symbols, and emit non-relocatable fixed offsets that will be fixed | |
| 369 | − * up at runtime. | |
| 370 | − * | |
| 371 | − * The symbol names cannot be used to construct normal symbol | |
| 372 | − * references as the list of symbols contains symbols that are | |
| 373 | − * declared static and are private to their .o files. This prevents | |
| 374 | − * .tmp_kallsyms.o or any other object from referencing them. | |
| 375 | − */ | |
| 376 | 372 | if (!base_relative) |
| 377 | 373 | output_label("kallsyms_addresses"); |
| 378 | 374 | else |
| @@ -380,6 +376,13 @@ static void write_src(void) · 1 unmodified line | ||
| 380 | 376 | |
| 381 | 377 | for (i = 0; i < table_cnt; i++) { |
| 382 | 378 | if (base_relative) { |
| 379 | + /* | |
| 380 | + * Use the offset relative to the lowest value | |
| 381 | + * encountered of all relative symbols, and emit | |
| 382 | + * non-relocatable fixed offsets that will be fixed | |
| 383 | + * up at runtime. | |
| 384 | + */ | |
| 385 | + | |
| 383 | 386 | long long offset; |
| 384 | 387 | int overflow; |
| 385 | 388 | |
| @@ -402,12 +405,7 @@ static void write_src(void) · 16 unmodified lines | ||
| 402 | 405 | } |
| 403 | 406 | printf("\t.long\t%#x\n", (int)offset); |
| 404 | 407 | } else if (!symbol_absolute(&table[i])) { |
| 405 | − if (_text <= table[i].addr) | |
| 406 | − printf("\tPTR\t_text + %#llx\n", | |
| 407 | − table[i].addr - _text); | |
| 408 | − else | |
| 409 | − printf("\tPTR\t_text - %#llx\n", | |
| 410 | − _text - table[i].addr); | |
| 408 | + output_address(table[i].addr); | |
| 411 | 409 | } else { |
| 412 | 410 | printf("\tPTR\t%#llx\n", table[i].addr); |
| 413 | 411 | } |
| @@ -416,7 +414,7 @@ static void write_src(void) · 2 unmodified lines | ||
| 416 | 414 | |
| 417 | 415 | if (base_relative) { |
| 418 | 416 | output_label("kallsyms_relative_base"); |
| 419 | − printf("\tPTR\t_text - %#llx\n", _text - relative_base); | |
| 417 | + output_address(relative_base); | |
| 420 | 418 | printf("\n"); |
| 421 | 419 | } |
| 422 | 420 | |