]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kallsyms: add support for relative offsets in kallsyms address table
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 9 Feb 2016 23:13:35 +0000 (10:13 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Tue, 9 Feb 2016 23:13:35 +0000 (10:13 +1100)
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Kees Cook <keescook@chromium.org>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Michal Marek <mmarek@suse.cz>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
init/Kconfig
kernel/kallsyms.c
scripts/kallsyms.c

index 028a71945ee3a1325be93a8d1a202def80d39e42..e17c7aaffc671959e4cf3db382c73049caecee22 100644 (file)
@@ -1449,13 +1449,15 @@ config KALLSYMS_ABSOLUTE_PERCPU
 config KALLSYMS_BASE_RELATIVE
        bool
        depends on KALLSYMS
-       default !IA64
+       default !IA64 && !(TILE && 64BIT)
        help
          Instead of emitting them as absolute values in the native word size,
          emit the symbol references in the kallsyms table as 32-bit entries,
-         each containing either an absolute value in the range [0, S32_MAX] or
-         a relative value in the range [base, base + S32_MAX], where base is
-         the lowest relative symbol address encountered in the image.
+         each containing a relative value in the range [base, base + U32_MAX]
+         or, when KALLSYMS_ABSOLUTE_PERCPU is in effect, each containing either
+         an absolute value in the range [0, S32_MAX] or a relative value in the
+         range [base, base + S32_MAX], where base is the lowest relative symbol
+         address encountered in the image.
 
          On 64-bit builds, this reduces the size of the address table by 50%,
          but more importantly, it results in entries whose values are build
index 10a8af9d574447b6608758c7a61d228f32ff34ab..fafd1a3ef0da56c6887fb5edd631e8e4a925a0e4 100644 (file)
@@ -185,11 +185,15 @@ static unsigned long kallsyms_sym_address(int idx)
        if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
                return kallsyms_addresses[idx];
 
-       /* positive offsets are absolute values */
+       /* values are unsigned offsets if --absolute-percpu is not in effect */
+       if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
+               return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
+
+       /* ...otherwise, positive offsets are absolute values */
        if (kallsyms_offsets[idx] >= 0)
                return kallsyms_offsets[idx];
 
-       /* negative offsets are relative to kallsyms_relative_base - 1 */
+       /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
        return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
 }
 
index 02473b71643b6093bbc6711df67f710c148d4695..638b143ee60f4246cc16d67936bc62095a66c646 100644 (file)
@@ -375,23 +375,24 @@ static void write_src(void)
        for (i = 0; i < table_cnt; i++) {
                if (base_relative) {
                        long long offset;
+                       int overflow;
 
-                       if (symbol_absolute(&table[i])) {
+                       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;
-                               if (offset < 0 || offset > INT_MAX) {
-                                       fprintf(stderr, "kallsyms failure: "
-                                               "absolute symbol value %#llx out of range in relative mode\n",
-                                               table[i].addr);
-                                       exit(EXIT_FAILURE);
-                               }
+                               overflow = (offset < 0 || offset > INT_MAX);
                        } else {
                                offset = relative_base - table[i].addr - 1;
-                               if (offset < INT_MIN || offset >= 0) {
-                                       fprintf(stderr, "kallsyms failure: "
-                                               "relative symbol value %#llx out of range in relative mode\n",
-                                               table[i].addr);
-                                       exit(EXIT_FAILURE);
-                               }
+                               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])) {
@@ -742,21 +743,11 @@ static void record_relative_base(void)
 {
        unsigned int i;
 
-       if (kernel_start_addr > 0) {
-               /*
-                * If the kernel start address was specified, use that as
-                * the relative base rather than going through the table,
-                * since it should be a reasonable default, and values below
-                * it will be ignored anyway.
-                */
-               relative_base = kernel_start_addr;
-       } else {
-               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;
-       }
+       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)