aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/kallsyms.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kallsyms.c')
-rw-r--r--scripts/kallsyms.c79
1 files changed, 69 insertions, 10 deletions
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index d39a1eeb080e..638b143ee60f 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -22,6 +22,7 @@
22#include <stdlib.h> 22#include <stdlib.h>
23#include <string.h> 23#include <string.h>
24#include <ctype.h> 24#include <ctype.h>
25#include <limits.h>
25 26
26#ifndef ARRAY_SIZE 27#ifndef ARRAY_SIZE
27#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 28#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -43,6 +44,7 @@ struct addr_range {
43}; 44};
44 45
45static unsigned long long _text; 46static unsigned long long _text;
47static unsigned long long relative_base;
46static struct addr_range text_ranges[] = { 48static struct addr_range text_ranges[] = {
47 { "_stext", "_etext" }, 49 { "_stext", "_etext" },
48 { "_sinittext", "_einittext" }, 50 { "_sinittext", "_einittext" },
@@ -62,6 +64,7 @@ static int all_symbols = 0;
62static int absolute_percpu = 0; 64static int absolute_percpu = 0;
63static char symbol_prefix_char = '\0'; 65static char symbol_prefix_char = '\0';
64static unsigned long long kernel_start_addr = 0; 66static unsigned long long kernel_start_addr = 0;
67static int base_relative = 0;
65 68
66int token_profit[0x10000]; 69int token_profit[0x10000];
67 70
@@ -75,7 +78,7 @@ static void usage(void)
75 fprintf(stderr, "Usage: kallsyms [--all-symbols] " 78 fprintf(stderr, "Usage: kallsyms [--all-symbols] "
76 "[--symbol-prefix=<prefix char>] " 79 "[--symbol-prefix=<prefix char>] "
77 "[--page-offset=<CONFIG_PAGE_OFFSET>] " 80 "[--page-offset=<CONFIG_PAGE_OFFSET>] "
78 "< in.map > out.S\n"); 81 "[--base-relative] < in.map > out.S\n");
79 exit(1); 82 exit(1);
80} 83}
81 84
@@ -205,6 +208,8 @@ static int symbol_valid(struct sym_entry *s)
205 */ 208 */
206 static char *special_symbols[] = { 209 static char *special_symbols[] = {
207 "kallsyms_addresses", 210 "kallsyms_addresses",
211 "kallsyms_offsets",
212 "kallsyms_relative_base",
208 "kallsyms_num_syms", 213 "kallsyms_num_syms",
209 "kallsyms_names", 214 "kallsyms_names",
210 "kallsyms_markers", 215 "kallsyms_markers",
@@ -349,16 +354,48 @@ static void write_src(void)
349 354
350 printf("\t.section .rodata, \"a\"\n"); 355 printf("\t.section .rodata, \"a\"\n");
351 356
352 /* Provide proper symbols relocatability by their '_text' 357 /* Provide proper symbols relocatability by their relativeness
353 * relativeness. The symbol names cannot be used to construct 358 * to a fixed anchor point in the runtime image, either '_text'
354 * normal symbol references as the list of symbols contains 359 * for absolute address tables, in which case the linker will
355 * symbols that are declared static and are private to their 360 * emit the final addresses at build time. Otherwise, use the
356 * .o files. This prevents .tmp_kallsyms.o or any other 361 * offset relative to the lowest value encountered of all relative
357 * object from referencing them. 362 * symbols, and emit non-relocatable fixed offsets that will be fixed
363 * up at runtime.
364 *
365 * The symbol names cannot be used to construct normal symbol
366 * references as the list of symbols contains symbols that are
367 * declared static and are private to their .o files. This prevents
368 * .tmp_kallsyms.o or any other object from referencing them.
358 */ 369 */
359 output_label("kallsyms_addresses"); 370 if (!base_relative)
371 output_label("kallsyms_addresses");
372 else
373 output_label("kallsyms_offsets");
374
360 for (i = 0; i < table_cnt; i++) { 375 for (i = 0; i < table_cnt; i++) {
361 if (!symbol_absolute(&table[i])) { 376 if (base_relative) {
377 long long offset;
378 int overflow;
379
380 if (!absolute_percpu) {
381 offset = table[i].addr - relative_base;
382 overflow = (offset < 0 || offset > UINT_MAX);
383 } else if (symbol_absolute(&table[i])) {
384 offset = table[i].addr;
385 overflow = (offset < 0 || offset > INT_MAX);
386 } else {
387 offset = relative_base - table[i].addr - 1;
388 overflow = (offset < INT_MIN || offset >= 0);
389 }
390 if (overflow) {
391 fprintf(stderr, "kallsyms failure: "
392 "%s symbol value %#llx out of range in relative mode\n",
393 symbol_absolute(&table[i]) ? "absolute" : "relative",
394 table[i].addr);
395 exit(EXIT_FAILURE);
396 }
397 printf("\t.long\t%#x\n", (int)offset);
398 } else if (!symbol_absolute(&table[i])) {
362 if (_text <= table[i].addr) 399 if (_text <= table[i].addr)
363 printf("\tPTR\t_text + %#llx\n", 400 printf("\tPTR\t_text + %#llx\n",
364 table[i].addr - _text); 401 table[i].addr - _text);
@@ -371,6 +408,12 @@ static void write_src(void)
371 } 408 }
372 printf("\n"); 409 printf("\n");
373 410
411 if (base_relative) {
412 output_label("kallsyms_relative_base");
413 printf("\tPTR\t_text - %#llx\n", _text - relative_base);
414 printf("\n");
415 }
416
374 output_label("kallsyms_num_syms"); 417 output_label("kallsyms_num_syms");
375 printf("\tPTR\t%d\n", table_cnt); 418 printf("\tPTR\t%d\n", table_cnt);
376 printf("\n"); 419 printf("\n");
@@ -695,6 +738,18 @@ static void make_percpus_absolute(void)
695 } 738 }
696} 739}
697 740
741/* find the minimum non-absolute symbol address */
742static void record_relative_base(void)
743{
744 unsigned int i;
745
746 relative_base = -1ULL;
747 for (i = 0; i < table_cnt; i++)
748 if (!symbol_absolute(&table[i]) &&
749 table[i].addr < relative_base)
750 relative_base = table[i].addr;
751}
752
698int main(int argc, char **argv) 753int main(int argc, char **argv)
699{ 754{
700 if (argc >= 2) { 755 if (argc >= 2) {
@@ -713,7 +768,9 @@ int main(int argc, char **argv)
713 } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { 768 } else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
714 const char *p = &argv[i][14]; 769 const char *p = &argv[i][14];
715 kernel_start_addr = strtoull(p, NULL, 16); 770 kernel_start_addr = strtoull(p, NULL, 16);
716 } else 771 } else if (strcmp(argv[i], "--base-relative") == 0)
772 base_relative = 1;
773 else
717 usage(); 774 usage();
718 } 775 }
719 } else if (argc != 1) 776 } else if (argc != 1)
@@ -722,6 +779,8 @@ int main(int argc, char **argv)
722 read_map(stdin); 779 read_map(stdin);
723 if (absolute_percpu) 780 if (absolute_percpu)
724 make_percpus_absolute(); 781 make_percpus_absolute();
782 if (base_relative)
783 record_relative_base();
725 sort_symbols(); 784 sort_symbols();
726 optimize_token_table(); 785 optimize_token_table();
727 write_src(); 786 write_src();