diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/kallsyms.c | 79 | ||||
-rwxr-xr-x | scripts/link-vmlinux.sh | 4 | ||||
-rwxr-xr-x | scripts/namespace.pl | 2 |
3 files changed, 75 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 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <limits.h> #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) @@ -43,6 +44,7 @@ struct addr_range { }; static unsigned long long _text; +static unsigned long long relative_base; static struct addr_range text_ranges[] = { { "_stext", "_etext" }, { "_sinittext", "_einittext" }, @@ -62,6 +64,7 @@ static int all_symbols = 0; static int absolute_percpu = 0; static char symbol_prefix_char = '\0'; static unsigned long long kernel_start_addr = 0; +static int base_relative = 0; int token_profit[0x10000]; @@ -75,7 +78,7 @@ static void usage(void) fprintf(stderr, "Usage: kallsyms [--all-symbols] " "[--symbol-prefix=<prefix char>] " "[--page-offset=<CONFIG_PAGE_OFFSET>] " - "< in.map > out.S\n"); + "[--base-relative] < in.map > out.S\n"); exit(1); } @@ -205,6 +208,8 @@ static int symbol_valid(struct sym_entry *s) */ static char *special_symbols[] = { "kallsyms_addresses", + "kallsyms_offsets", + "kallsyms_relative_base", "kallsyms_num_syms", "kallsyms_names", "kallsyms_markers", @@ -349,16 +354,48 @@ static void write_src(void) printf("\t.section .rodata, \"a\"\n"); - /* Provide proper symbols relocatability by their '_text' - * relativeness. The symbol names cannot be used to construct - * normal symbol references as the list of symbols contains - * symbols that are declared static and are private to their - * .o files. This prevents .tmp_kallsyms.o or any other - * object from referencing them. + /* Provide proper symbols relocatability by their relativeness + * to a fixed anchor point in the runtime image, either '_text' + * for absolute address tables, in which case the linker will + * emit the final addresses at build time. Otherwise, use the + * offset relative to the lowest value encountered of all relative + * symbols, and emit non-relocatable fixed offsets that will be fixed + * up at runtime. + * + * The symbol names cannot be used to construct normal symbol + * references as the list of symbols contains symbols that are + * declared static and are private to their .o files. This prevents + * .tmp_kallsyms.o or any other object from referencing them. */ - output_label("kallsyms_addresses"); + if (!base_relative) + output_label("kallsyms_addresses"); + else + output_label("kallsyms_offsets"); + for (i = 0; i < table_cnt; i++) { - if (!symbol_absolute(&table[i])) { + if (base_relative) { + long long offset; + int overflow; + + if (!absolute_percpu) { + offset = table[i].addr - relative_base; + overflow = (offset < 0 || offset > UINT_MAX); + } else if (symbol_absolute(&table[i])) { + offset = table[i].addr; + overflow = (offset < 0 || offset > INT_MAX); + } else { + offset = relative_base - table[i].addr - 1; + overflow = (offset < INT_MIN || offset >= 0); + } + if (overflow) { + fprintf(stderr, "kallsyms failure: " + "%s symbol value %#llx out of range in relative mode\n", + symbol_absolute(&table[i]) ? "absolute" : "relative", + table[i].addr); + exit(EXIT_FAILURE); + } + printf("\t.long\t%#x\n", (int)offset); + } else if (!symbol_absolute(&table[i])) { if (_text <= table[i].addr) printf("\tPTR\t_text + %#llx\n", table[i].addr - _text); @@ -371,6 +408,12 @@ static void write_src(void) } printf("\n"); + if (base_relative) { + output_label("kallsyms_relative_base"); + printf("\tPTR\t_text - %#llx\n", _text - relative_base); + printf("\n"); + } + output_label("kallsyms_num_syms"); printf("\tPTR\t%d\n", table_cnt); printf("\n"); @@ -695,6 +738,18 @@ static void make_percpus_absolute(void) } } +/* find the minimum non-absolute symbol address */ +static void record_relative_base(void) +{ + unsigned int i; + + relative_base = -1ULL; + for (i = 0; i < table_cnt; i++) + if (!symbol_absolute(&table[i]) && + table[i].addr < relative_base) + relative_base = table[i].addr; +} + int main(int argc, char **argv) { if (argc >= 2) { @@ -713,7 +768,9 @@ int main(int argc, char **argv) } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { const char *p = &argv[i][14]; kernel_start_addr = strtoull(p, NULL, 16); - } else + } else if (strcmp(argv[i], "--base-relative") == 0) + base_relative = 1; + else usage(); } } else if (argc != 1) @@ -722,6 +779,8 @@ int main(int argc, char **argv) read_map(stdin); if (absolute_percpu) make_percpus_absolute(); + if (base_relative) + record_relative_base(); sort_symbols(); optimize_token_table(); write_src(); diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 7a08bf9a9576..453ede9d2f3d 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -90,6 +90,10 @@ kallsyms() kallsymopt="${kallsymopt} --absolute-percpu" fi + if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then + kallsymopt="${kallsymopt} --base-relative" + fi + local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" diff --git a/scripts/namespace.pl b/scripts/namespace.pl index a71be6b7cdec..9f3c9d47a4a5 100755 --- a/scripts/namespace.pl +++ b/scripts/namespace.pl @@ -117,6 +117,8 @@ my %nameexception = ( 'kallsyms_names' => 1, 'kallsyms_num_syms' => 1, 'kallsyms_addresses'=> 1, + 'kallsyms_offsets' => 1, + 'kallsyms_relative_base'=> 1, '__this_module' => 1, '_etext' => 1, '_edata' => 1, |