From 164327623b8ad256eb644a2925568c7ce220e627 Mon Sep 17 00:00:00 2001 From: Andreas Abel Date: Wed, 7 Sep 2016 17:03:20 -0700 Subject: [PATCH] lkl: Add a config option to select section for kallsyms This commit adds a kernel config option to select whether the kallsyms data should be in the .rodata section (the default for non-LKL builds), or in the .data section (the default for LKL). This is to avoid relocations in the text segment (TEXTRELs) that would otherwise occur with LKL when the .rodata and the .text section end up in the same segment. Having TEXTRELs can lead to a number of issues: 1. If a shared library contains a TEXTREL, the corresponding memory pages cannot be shared. 2. Android >=6 and SELinux do not support binaries with TEXTRELs (http://android-developers.blogspot.com/2016/06/android-changes-for-ndk-developers.html). 3. If a program has a TEXTREL, uses an ifunc, and is compiled with early binding, this can lead to a segmentation fault when processing the relocation for the ifunc during dynamic linking because the text segment is made temporarily non-executable to process the TEXTREL (line 248 in dl_reloc.c). Signed-off-by: Andreas Abel --- arch/lkl/defconfig | 1 + init/Kconfig | 12 ++++++++++++ scripts/kallsyms.c | 17 ++++++++++++----- scripts/link-vmlinux.sh | 4 ++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/arch/lkl/defconfig b/arch/lkl/defconfig index 43d30584195291..f91380beee7c38 100644 --- a/arch/lkl/defconfig +++ b/arch/lkl/defconfig @@ -1,6 +1,7 @@ # CONFIG_LOCALVERSION_AUTO is not set CONFIG_NO_HZ_IDLE=y # CONFIG_SYSFS_SYSCALL is not set +CONFIG_KALLSYMS_USE_DATA_SECTION=y CONFIG_KALLSYMS_ALL=y # CONFIG_BASE_FULL is not set # CONFIG_FUTEX is not set diff --git a/init/Kconfig b/init/Kconfig index 0dfd09d54c6519..2f47a3c238adf5 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1443,6 +1443,18 @@ config KALLSYMS_BASE_RELATIVE time constants, and no relocation pass is required at runtime to fix up the entries based on the runtime load address of the kernel. +config KALLSYMS_USE_DATA_SECTION + bool "Use .data instead of .rodata section for kallsyms" + depends on KALLSYMS + default n + help + Enabling this option will put the kallsyms data in the .data section + instead of the .rodata section. + + This is useful when building the kernel as a library, as it avoids + relocations in the text segment that could otherwise occur if the + .rodata section is in the same segment as the .text section. + config PRINTK default y bool "Enable support for printk" if EXPERT diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 638b143ee60f42..a5d5c4495aec7f 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -60,11 +60,12 @@ static struct addr_range percpu_range = { static struct sym_entry *table; static unsigned int table_size, table_cnt; -static int all_symbols = 0; -static int absolute_percpu = 0; +static int all_symbols; +static int use_data_section; +static int absolute_percpu; static char symbol_prefix_char = '\0'; -static unsigned long long kernel_start_addr = 0; -static int base_relative = 0; +static unsigned long long kernel_start_addr; +static int base_relative; int token_profit[0x10000]; @@ -76,6 +77,7 @@ unsigned char best_table_len[256]; static void usage(void) { fprintf(stderr, "Usage: kallsyms [--all-symbols] " + "[--use-data-section] " "[--symbol-prefix=] " "[--page-offset=] " "[--base-relative] < in.map > out.S\n"); @@ -352,7 +354,10 @@ static void write_src(void) printf("#define ALGN .align 4\n"); printf("#endif\n"); - printf("\t.section .rodata, \"a\"\n"); + if (use_data_section) + printf("\t.section .data\n"); + else + printf("\t.section .rodata, \"a\"\n"); /* Provide proper symbols relocatability by their relativeness * to a fixed anchor point in the runtime image, either '_text' @@ -759,6 +764,8 @@ int main(int argc, char **argv) all_symbols = 1; else if (strcmp(argv[i], "--absolute-percpu") == 0) absolute_percpu = 1; + else if (strcmp(argv[i], "--use-data-section") == 0) + use_data_section = 1; else if (strncmp(argv[i], "--symbol-prefix=", 16) == 0) { char *p = &argv[i][16]; /* skip quote */ diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 8d3eedefe06b2b..ff5267e1d07562 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -94,6 +94,10 @@ kallsyms() kallsymopt="${kallsymopt} --base-relative" fi + if [ -n "${CONFIG_KALLSYMS_USE_DATA_SECTION}" ]; then + kallsymopt="${kallsymopt} --use-data-section" + fi + local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"