From a05e8fd9ff146fe2cd3978093e1075f9a7ad2206 Mon Sep 17 00:00:00 2001 From: Stuart Ianna Date: Fri, 26 May 2023 14:22:36 +1000 Subject: [PATCH] binfmt/elf: Support loading fully linked executables. The following changes make it possible for Nuttx to load binaries in ELF format which are fully linked. The change does not include the necessary modifications to produce such binaries. In order to build an applicable binary: - The userspace applications linker script (`gnu-elf.ld`) needs to modified so the data and text section origin's match those setup by the address environment. - The makefile used, in `apps/import/Make.defs` needs to remove the `-r` LDELFFLAG. --- binfmt/elf.c | 34 +++++++++++++++++++++++++++++----- binfmt/libelf/libelf_verify.c | 5 +++-- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/binfmt/elf.c b/binfmt/elf.c index 56e6197d21..8896e35b27 100644 --- a/binfmt/elf.c +++ b/binfmt/elf.c @@ -247,16 +247,40 @@ static int elf_loadbinary(FAR struct binary_s *binp, /* Bind the program to the exported symbol table */ - ret = elf_bind(&loadinfo, exports, nexports); - if (ret != 0) + if (loadinfo.ehdr.e_type == ET_REL) { - berr("Failed to bind symbols program binary: %d\n", ret); - goto errout_with_load; + ret = elf_bind(&loadinfo, exports, nexports); + if (ret != 0) + { + berr("Failed to bind symbols program binary: %d\n", ret); + goto errout_with_load; + } + + binp->entrypt = (main_t)(loadinfo.textalloc + loadinfo.ehdr.e_entry); + } + else if (loadinfo.ehdr.e_type == ET_EXEC) + { + if (nexports > 0) + { + berr("Cannot bind exported symbols to a "\ + "fully linked executable\n"); + ret = -ENOEXEC; + goto errout_with_load; + } + + /* The entrypoint for a fully linked executable can be found directly */ + + binp->entrypt = (main_t)(loadinfo.ehdr.e_entry); + } + + else + { + berr("Unexpected elf type %d\n", loadinfo.ehdr.e_type); + ret = -ENOEXEC; } /* Return the load information */ - binp->entrypt = (main_t)(loadinfo.textalloc + loadinfo.ehdr.e_entry); binp->stacksize = CONFIG_ELF_STACKSIZE; /* Add the ELF allocation to the alloc[] only if there is no address diff --git a/binfmt/libelf/libelf_verify.c b/binfmt/libelf/libelf_verify.c index 3e6f0a5c66..09217d49ea 100644 --- a/binfmt/libelf/libelf_verify.c +++ b/binfmt/libelf/libelf_verify.c @@ -89,9 +89,10 @@ int elf_verifyheader(FAR const Elf_Ehdr *ehdr) /* Verify that this is a relocatable file */ - if (ehdr->e_type != ET_REL) + if ((ehdr->e_type != ET_REL) && (ehdr->e_type != ET_EXEC)) { - berr("Not a relocatable file: e_type=%d\n", ehdr->e_type); + berr("Not a relocatable or executable file: e_type=%d\n", + ehdr->e_type); return -EINVAL; }