diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2017-02-03 09:54:05 +0000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-03 08:28:25 -0800 |
commit | 56067812d5b0e737ac2063e94a50f76b810d6ca3 (patch) | |
tree | 1627e6abc9001f0b519ed65daa86be46d52c4117 /scripts/mod | |
parent | 34e00accf612bc5448ae709245c2b408edf39f46 (diff) | |
download | lwn-56067812d5b0e737ac2063e94a50f76b810d6ca3.tar.gz lwn-56067812d5b0e737ac2063e94a50f76b810d6ca3.zip |
kbuild: modversions: add infrastructure for emitting relative CRCs
This add the kbuild infrastructure that will allow architectures to emit
vmlinux symbol CRCs as 32-bit offsets to another location in the kernel
where the actual value is stored. This works around problems with CRCs
being mistaken for relocatable symbols on kernels that self relocate at
runtime (i.e., powerpc with CONFIG_RELOCATABLE=y)
For the kbuild side of things, this comes down to the following:
- introducing a Kconfig symbol MODULE_REL_CRCS
- adding a -R switch to genksyms to instruct it to emit the CRC symbols
as references into the .rodata section
- making modpost distinguish such references from absolute CRC symbols
by the section index (SHN_ABS)
- making kallsyms disregard non-absolute symbols with a __crc_ prefix
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts/mod')
-rw-r--r-- | scripts/mod/modpost.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 29c89a6bad3d..4dedd0d3d3a7 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -621,6 +621,16 @@ static void handle_modversions(struct module *mod, struct elf_info *info, if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { is_crc = true; crc = (unsigned int) sym->st_value; + if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) { + unsigned int *crcp; + + /* symbol points to the CRC in the ELF object */ + crcp = (void *)info->hdr + sym->st_value + + info->sechdrs[sym->st_shndx].sh_offset - + (info->hdr->e_type != ET_REL ? + info->sechdrs[sym->st_shndx].sh_addr : 0); + crc = *crcp; + } sym_update_crc(symname + strlen(CRC_PFX), mod, crc, export); } |