Re: [PATCH] MIPS: Use a custom elf-entry program to find kernel entry point

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Paul,

----- Le 29 Aoû 18, à 20:01, Paul Burton paul.burton@xxxxxxxx a écrit :

> For a long time arch/mips/Makefile used nm to discover the kernel entry
> point by looking for the address of the kernel_entry symbol. This
> doesn't work for systems which make use of bit 0 of the PC to reflect
> the ISA mode - ie. microMIPS (and MIPS16, but we don't support building
> kernels that target MIPS16 anyway).
> 
> So for a while with commit 5fc9484f5e41 ("MIPS: Set ISA bit in entry-y
> for microMIPS kernels") we manually modified the last nibble of the
> output from nm, which worked but wasn't particularly pretty.
> 
> Commit 27c524d17430 ("MIPS: Use the entry point from the ELF file
> header") then cleaned this up by using objdump to print the ELF entry
> point which includes the ISA bit, rather than using nm to print the
> address of the kernel_entry symbol which doesn't. That removed the ugly
> replacement of the last nibble, but added its own ugliness by needing to
> manually sign extend in the 32 bit case.
> 
> Unfortunately it has been pointed out that objdump's output is
> localised, and therefore grepping for its "start address" output doesn't
> work when the user's language settings are such that objdump doesn't
> print in English.
> 
> We could simply revert commit 27c524d17430 ("MIPS: Use the entry point
> from the ELF file header") and return to the manual replacement of the
> last nibble of entry-y, but it seems that was found sufficiently
> unpalatable to avoid. We could attempt to force the language used by
> objdump by setting an environment variable such as LC_ALL, but that
> seems fragile. Instead we add a small tool named elf-entry which simply
> prints out the entry point of the kernel in the format we require.
> 
> Signed-off-by: Paul Burton <paul.burton@xxxxxxxx>
> Reported-by: Philippe Reynes <philippe.reynes@xxxxxxxxxxxxxx>
> Fixes: 27c524d17430 ("MIPS: Use the entry point from the ELF file header")
> Cc: James Hogan <jhogan@xxxxxxxxxx>
> Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx>
> Cc: linux-mips@xxxxxxxxxxxxxx

I've tested on my "french" machine, and it works fine.

Tested-by: Philippe Reynes <philippe.reynes@xxxxxxxxxxxxxx>

> ---
> arch/mips/Makefile | 9 +---
> arch/mips/tools/.gitignore | 1 +
> arch/mips/tools/Makefile | 5 ++
> arch/mips/tools/elf-entry.c | 96 +++++++++++++++++++++++++++++++++++++
> 4 files changed, 104 insertions(+), 7 deletions(-)
> create mode 100644 arch/mips/tools/.gitignore
> create mode 100644 arch/mips/tools/Makefile
> create mode 100644 arch/mips/tools/elf-entry.c
> 
> diff --git a/arch/mips/Makefile b/arch/mips/Makefile
> index d74b3742fa5d..053e1c314f9e 100644
> --- a/arch/mips/Makefile
> +++ b/arch/mips/Makefile
> @@ -13,6 +13,7 @@
> #
> 
> archscripts: scripts_basic
> + $(Q)$(MAKE) $(build)=arch/mips/tools elf-entry
> $(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs
> 
> KBUILD_DEFCONFIG := 32r2el_defconfig
> @@ -257,13 +258,7 @@ ifdef CONFIG_PHYSICAL_START
> load-y = $(CONFIG_PHYSICAL_START)
> endif
> 
> -# Sign-extend the entry point to 64 bits if retrieved as a 32-bit number.
> -entry-y = $(shell $(OBJDUMP) -f vmlinux 2>/dev/null \
> - | sed -n '/^start address / { \
> - s/^.* //; \
> - s/0x\([0-7].......\)$$/0x00000000\1/; \
> - s/0x\(........\)$$/0xffffffff\1/; p }')
> -
> +entry-y = $(shell $(objtree)/arch/mips/tools/elf-entry vmlinux)
> cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
> drivers-$(CONFIG_PCI) += arch/mips/pci/
> 
> diff --git a/arch/mips/tools/.gitignore b/arch/mips/tools/.gitignore
> new file mode 100644
> index 000000000000..56d34ccccce4
> --- /dev/null
> +++ b/arch/mips/tools/.gitignore
> @@ -0,0 +1 @@
> +elf-entry
> diff --git a/arch/mips/tools/Makefile b/arch/mips/tools/Makefile
> new file mode 100644
> index 000000000000..3baee4bc6775
> --- /dev/null
> +++ b/arch/mips/tools/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0
> +hostprogs-y := elf-entry
> +PHONY += elf-entry
> +elf-entry: $(obj)/elf-entry
> + @:
> diff --git a/arch/mips/tools/elf-entry.c b/arch/mips/tools/elf-entry.c
> new file mode 100644
> index 000000000000..adde79ce7fc0
> --- /dev/null
> +++ b/arch/mips/tools/elf-entry.c
> @@ -0,0 +1,96 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <byteswap.h>
> +#include <elf.h>
> +#include <endian.h>
> +#include <inttypes.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#ifdef be32toh
> +/* If libc provides [bl]e{32,64}toh() then we'll use them */
> +#elif BYTE_ORDER == LITTLE_ENDIAN
> +# define be32toh(x) bswap_32(x)
> +# define le32toh(x) (x)
> +# define be64toh(x) bswap_64(x)
> +# define le64toh(x) (x)
> +#elif BYTE_ORDER == BIG_ENDIAN
> +# define be32toh(x) (x)
> +# define le32toh(x) bswap_32(x)
> +# define be64toh(x) (x)
> +# define le64toh(x) bswap_64(x)
> +#endif
> +
> +__attribute__((noreturn))
> +static void die(const char *msg)
> +{
> + fputs(msg, stderr);
> + exit(EXIT_FAILURE);
> +}
> +
> +int main(int argc, const char *argv[])
> +{
> + uint64_t entry;
> + size_t nread;
> + FILE *file;
> + union {
> + Elf32_Ehdr ehdr32;
> + Elf64_Ehdr ehdr64;
> + } hdr;
> +
> + if (argc != 2)
> + die("Usage: elf-entry <elf-file>\n");
> +
> + file = fopen(argv[1], "r");
> + if (!file) {
> + perror("Unable to open input file");
> + return EXIT_FAILURE;
> + }
> +
> + nread = fread(&hdr, 1, sizeof(hdr), file);
> + if (nread != sizeof(hdr)) {
> + perror("Unable to read input file");
> + return EXIT_FAILURE;
> + }
> +
> + if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG))
> + die("Input is not an ELF\n");
> +
> + switch (hdr.ehdr32.e_ident[EI_CLASS]) {
> + case ELFCLASS32:
> + switch (hdr.ehdr32.e_ident[EI_DATA]) {
> + case ELFDATA2LSB:
> + entry = le32toh(hdr.ehdr32.e_entry);
> + break;
> + case ELFDATA2MSB:
> + entry = be32toh(hdr.ehdr32.e_entry);
> + break;
> + default:
> + die("Invalid ELF encoding\n");
> + }
> +
> + /* Sign extend to form a canonical address */
> + entry = (int64_t)(int32_t)entry;
> + break;
> +
> + case ELFCLASS64:
> + switch (hdr.ehdr32.e_ident[EI_DATA]) {
> + case ELFDATA2LSB:
> + entry = le64toh(hdr.ehdr64.e_entry);
> + break;
> + case ELFDATA2MSB:
> + entry = be64toh(hdr.ehdr64.e_entry);
> + break;
> + default:
> + die("Invalid ELF encoding\n");
> + }
> + break;
> +
> + default:
> + die("Invalid ELF class\n");
> + }
> +
> + printf("0x%016" PRIx64 "\n", entry);
> + return EXIT_SUCCESS;
> +}
> --
> 2.18.0




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux