diff --git a/apps/examples/README.txt b/apps/examples/README.txt index 763427e326..fa97bd64e3 100644 --- a/apps/examples/README.txt +++ b/apps/examples/README.txt @@ -297,6 +297,53 @@ examples/discover CONFIG_EXAMPLES_DISCOVER_DRIPADDR - Router IP address CONFIG_EXAMPLES_DISCOVER_NETMASK - Network Mask +examples/elf +^^^^^^^^^^^^ + + This example builds a small ELF loader test case. This includes several + test programs under examples/elf tests. These tests are build using + the relocatable ELF format and installed in a ROMFS file system. At run time, + each program in the ROMFS file system is executed. Requires CONFIG_ELF. + Other configuration options: + + CONFIG_EXAMPLES_ELF_DEVMINOR - The minor device number of the ROMFS block. + For example, the N in /dev/ramN. Used for registering the RAM block driver + that will hold the ROMFS file system containing the ELF executables to be + tested. Default: 0 + + CONFIG_EXAMPLES_ELF_DEVPATH - The path to the ROMFS block driver device. This + must match EXAMPLES_ELF_DEVMINOR. Used for registering the RAM block driver + that will hold the ROMFS file system containing the ELF executables to be + tested. Default: "/dev/ram0" + + NOTES: + + 1. Your top-level nuttx/Make.defs file must include an approproate definition, + LDELFFLAGS, to generate a relocatable ELF object. With GNU LD, this should + include '-r' and '-e main' (or _main on some platforms). + + LDELFFLAGS = -r -e main + + If you use GCC to link, you make also need to include '-nostdlib' or + '-nostartfiles' and '-nodefaultlibs'. + + 2. This example also requires genromfs. genromfs can be build as part of the + nuttx toolchain. Or can built from the genromfs sources that can be found + at misc/tools/genromfs-0.5.2.tar.gz. In any event, the PATH variable must + include the path to the genromfs executable. + + 3. ELF size: The ELF files in this example are, be default, quite large + because they include a lot of "build garbage". You can greately reduce the + size of the ELF binaries are using the objcopy --strip-unneeded command to + remove un-necessary information from the ELF files. + + 4. Simulator. You cannot use this example with the the NuttX simulator on + Cygwin. That is because the Cygwin GCC does not generate ELF file but + rather some Windows-native binary format. + + If you really want to do this, you can create a NuttX x86 buildroot toolchain + and use that be build the ELF executables for the ROMFS file system. + examples/ftpc ^^^^^^^^^^^^^ diff --git a/apps/examples/elf/Kconfig b/apps/examples/elf/Kconfig index aca36f1b9b..c62a98486e 100644 --- a/apps/examples/elf/Kconfig +++ b/apps/examples/elf/Kconfig @@ -10,4 +10,20 @@ config EXAMPLES_ELF Enable the ELF loader example if EXAMPLES_ELF +config EXAMPLES_ELF_DEVMINOR + int "ROMFS Minor Device Number" + default 0 + ---help--- + The minor device number of the ROMFS block. For example, the N in /dev/ramN. + Used for registering the RAM block driver that will hold the ROMFS file system + containing the ELF executables to be tested. Default: 0 + +config EXAMPLES_ELF_DEVPATH + string "ROMFS Devie Path" + default "/dev/ram0" + ---help--- + The path to the ROMFS block driver device. This must match EXAMPLES_ELF_DEVMINOR. + Used for registering the RAM block driver that will hold the ROMFS file system + containing the ELF executables to be tested. Default: "/dev/ram0" + endif diff --git a/apps/examples/elf/Makefile b/apps/examples/elf/Makefile index 640e8e427d..23a6bcb6fe 100644 --- a/apps/examples/elf/Makefile +++ b/apps/examples/elf/Makefile @@ -61,7 +61,7 @@ ROOTDEPPATH = --dep-path . VPATH = all: .built -.PHONY: headers clean depend disclean +.PHONY: headers clean_tests clean depend disclean $(AOBJS): %$(OBJEXT): %.S $(call ASSEMBLE, $<, $@) @@ -72,7 +72,7 @@ $(COBJS): %$(OBJEXT): %.c headers: @$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) -.built: $(OBJS) +.built: headers $(OBJS) @( for obj in $(OBJS) ; do \ $(call ARCHIVE, $(BIN), $${obj}); \ done ; ) @@ -88,7 +88,10 @@ context: depend: .depend -clean: +clean_tests: + @$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) clean + +clean: clean_tests @rm -f *.o *~ .*.swp .built $(call CLEAN) diff --git a/apps/examples/elf/elf_main b/apps/examples/elf/elf_main.c similarity index 91% rename from apps/examples/elf/elf_main rename to apps/examples/elf/elf_main.c index c58b13ffc2..5699dd2849 100644 --- a/apps/examples/elf/elf_main +++ b/apps/examples/elf/elf_main.c @@ -89,9 +89,16 @@ #define SECTORSIZE 512 #define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE) -#define ROMFSDEV "/dev/ram0" #define MOUNTPT "/mnt/romfs" +#ifndef CONFIG_EXAMPLES_ELF_DEVMINOR +# define CONFIG_EXAMPLES_ELF_DEVMINOR 0 +#endif + +#ifndef CONFIG_EXAMPLES_ELF_DEVPATH +# define CONFIG_EXAMPLES_ELF_DEVPATH "/dev/ram0" +#endif + /* If CONFIG_DEBUG is enabled, use dbg instead of printf so that the * output will be synchronous with the debug output. */ @@ -166,8 +173,9 @@ int elf_main(int argc, char *argv[]) /* Create a ROM disk for the ROMFS filesystem */ - message("Registering romdisk\n"); - ret = romdisk_register(0, romfs_img, NSECTORS(romfs_img_len), SECTORSIZE); + message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR); + ret = romdisk_register(CONFIG_EXAMPLES_ELF_DEVMINOR, romfs_img, + NSECTORS(romfs_img_len), SECTORSIZE); if (ret < 0) { err("ERROR: romdisk_register failed: %d\n", ret); @@ -178,13 +186,13 @@ int elf_main(int argc, char *argv[]) /* Mount the file system */ message("Mounting ROMFS filesystem at target=%s with source=%s\n", - MOUNTPT, ROMFSDEV); + MOUNTPT, CONFIG_EXAMPLES_ELF_DEVPATH); - ret = mount(ROMFSDEV, MOUNTPT, "romfs", MS_RDONLY, NULL); + ret = mount(CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, "romfs", MS_RDONLY, NULL); if (ret < 0) { err("ERROR: mount(%s,%s,romfs) failed: %s\n", - ROMFSDEV, MOUNTPT, errno); + CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, errno); elf_uninitialize(); } @@ -219,6 +227,6 @@ int elf_main(int argc, char *argv[]) sleep(4); } - message("End-of-Test.. Exit-ing\n"); + message("End-of-Test.. Exiting\n"); return 0; } diff --git a/apps/examples/elf/tests/errno/Makefile b/apps/examples/elf/tests/errno/Makefile index d3b12aa2ec..3c299b16df 100644 --- a/apps/examples/elf/tests/errno/Makefile +++ b/apps/examples/elf/tests/errno/Makefile @@ -39,7 +39,7 @@ BIN = errno SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/apps/examples/elf/tests/hello++/Makefile b/apps/examples/elf/tests/hello++/Makefile index b3d07d2626..9de52cfa10 100644 --- a/apps/examples/elf/tests/hello++/Makefile +++ b/apps/examples/elf/tests/hello++/Makefile @@ -64,7 +64,7 @@ all: $(BIN1) $(BIN2) $(BIN3) $(BIN4) $(OBJS): %.o: %.cpp @echo "CC: $<" - @$(CXX) -c $(CXXPICFLAGS) $< -o $@ + @$(CXX) -c $(CXXFLAGS) $< -o $@ # This contains libstdc++ stubs to that you can build C++ code # without actually having libstdc++ diff --git a/apps/examples/elf/tests/hello/Makefile b/apps/examples/elf/tests/hello/Makefile index 3b9b06ac42..c3a3dacaf1 100644 --- a/apps/examples/elf/tests/hello/Makefile +++ b/apps/examples/elf/tests/hello/Makefile @@ -39,7 +39,7 @@ BIN = hello SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/apps/examples/elf/tests/longjmp/Makefile b/apps/examples/elf/tests/longjmp/Makefile index 12d6e443cd..d737718e05 100644 --- a/apps/examples/elf/tests/longjmp/Makefile +++ b/apps/examples/elf/tests/longjmp/Makefile @@ -39,7 +39,7 @@ BIN = longjmp SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/apps/examples/elf/tests/mutex/Makefile b/apps/examples/elf/tests/mutex/Makefile index 632fed9dd4..7f0a5493e9 100644 --- a/apps/examples/elf/tests/mutex/Makefile +++ b/apps/examples/elf/tests/mutex/Makefile @@ -39,7 +39,7 @@ BIN = mutex SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/apps/examples/elf/tests/pthread/Makefile b/apps/examples/elf/tests/pthread/Makefile index fae6144c26..8db290e6ea 100644 --- a/apps/examples/elf/tests/pthread/Makefile +++ b/apps/examples/elf/tests/pthread/Makefile @@ -39,7 +39,7 @@ BIN = pthread SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/apps/examples/elf/tests/signal/Makefile b/apps/examples/elf/tests/signal/Makefile index 2704440324..4338aa48da 100644 --- a/apps/examples/elf/tests/signal/Makefile +++ b/apps/examples/elf/tests/signal/Makefile @@ -39,7 +39,7 @@ BIN = signal SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/apps/examples/elf/tests/struct/Makefile b/apps/examples/elf/tests/struct/Makefile index f98a65e25f..c15d8fc476 100644 --- a/apps/examples/elf/tests/struct/Makefile +++ b/apps/examples/elf/tests/struct/Makefile @@ -38,7 +38,7 @@ CFLAGS += -I. -BIN = struct +BIN = struct SRCS = struct_main.c struct_dummy.c OBJS = $(SRCS:.c=.o) diff --git a/apps/examples/elf/tests/task/Makefile b/apps/examples/elf/tests/task/Makefile index 28047965ed..208b228b3a 100644 --- a/apps/examples/elf/tests/task/Makefile +++ b/apps/examples/elf/tests/task/Makefile @@ -39,7 +39,7 @@ BIN = task SRCS = $(BIN).c -OBJS = $(BIN:.c=.o) +OBJS = $(SRCS:.c=.o) all: $(BIN) diff --git a/nuttx/Makefile b/nuttx/Makefile index 7a058d88e9..73bffc3014 100644 --- a/nuttx/Makefile +++ b/nuttx/Makefile @@ -644,7 +644,7 @@ ifneq ($(APPDIR),) fi @$(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" distclean @if [ -r _SAVED_APPS_config ]; then \ - @mv _SAVED_APPS_config "$(TOPDIR)/$(APPDIR)/.config" || \ + mv _SAVED_APPS_config "$(TOPDIR)/$(APPDIR)/.config" || \ { echo "Copy of _SAVED_APPS_config failed" ; exit 1 ; } \ fi endif diff --git a/nuttx/arch/sim/src/up_elf.c b/nuttx/arch/sim/src/up_elf.c index c6aabdcef7..ca3b642dcd 100644 --- a/nuttx/arch/sim/src/up_elf.c +++ b/nuttx/arch/sim/src/up_elf.c @@ -40,7 +40,9 @@ #include #include +#include #include +#include #include #include @@ -113,7 +115,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym, { FAR uint32_t *ptr = (FAR uint32_t *)addr; - switch (ELF_REL_TYPE(rel->r_info)) + switch (ELF32_R_TYPE(rel->r_info)) { case R_386_32: *ptr += sym->st_value; diff --git a/nuttx/arch/x86/src/common/up_elf.c b/nuttx/arch/x86/src/common/up_elf.c index f159c8e518..be166b480c 100644 --- a/nuttx/arch/x86/src/common/up_elf.c +++ b/nuttx/arch/x86/src/common/up_elf.c @@ -40,7 +40,9 @@ #include #include +#include #include +#include #include #include @@ -113,7 +115,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym, { FAR uint32_t *ptr = (FAR uint32_t *)addr; - switch (ELF_REL_TYPE(rel->r_info)) + switch (ELF32_R_TYPE(rel->r_info)) { case R_386_32: *ptr += sym->st_value; diff --git a/nuttx/binfmt/elf.c b/nuttx/binfmt/elf.c index ba12a22ea4..d9c3d0b9c9 100644 --- a/nuttx/binfmt/elf.c +++ b/nuttx/binfmt/elf.c @@ -139,11 +139,11 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo) bdbg(" e_shnum: %d\n", loadinfo->ehdr.e_shnum); bdbg(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx); - if (loadinfo->shdr && loadinfo->ehdr.e_shum > 0) + if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0) { - for (i = 0; i < loadinfo->ehdr.e_shum; i++) + for (i = 0; i < loadinfo->ehdr.e_shnum; i++) { - FAR ELF32_Shdr *shdr = &loadinfo->shdr[i]; + FAR Elf32_Shdr *shdr = &loadinfo->shdr[i]; bdbg("Sections %d:\n", i); bdbg(" sh_name: %08x\n", shdr->sh_name); bdbg(" sh_type: %08x\n", shdr->sh_type); @@ -184,7 +184,7 @@ static int elf_loadbinary(struct binary_s *binp) elf_dumploadinfo(&loadinfo); if (ret != 0) { - bdbg("Failed to initialize for load of NXFLT program: %d\n", ret); + bdbg("Failed to initialize for load of ELF program: %d\n", ret); goto errout; } @@ -194,7 +194,7 @@ static int elf_loadbinary(struct binary_s *binp) elf_dumploadinfo(&loadinfo); if (ret != 0) { - bdbg("Failed to load NXFLT program binary: %d\n", ret); + bdbg("Failed to load ELF program binary: %d\n", ret); goto errout_with_init; } diff --git a/nuttx/binfmt/libelf/Make.defs b/nuttx/binfmt/libelf/Make.defs index 9e06537bd6..a70a127f80 100644 --- a/nuttx/binfmt/libelf/Make.defs +++ b/nuttx/binfmt/libelf/Make.defs @@ -41,7 +41,7 @@ BINFMT_CSRCS += elf.c # ELF library -BINFMT_CSRCS = libelf_init.c libelf_uninit.c libelf_load.c \ +BINFMT_CSRCS += libelf_init.c libelf_uninit.c libelf_load.c \ libelf_unload.c libelf_verify.c libelf_read.c \ libelf_bind.c libelf_symbols.c diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c index 758f965483..4a1a561c3c 100644 --- a/nuttx/binfmt/libelf/libelf_load.c +++ b/nuttx/binfmt/libelf/libelf_load.c @@ -283,8 +283,8 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) /* Update sh_addr to point to copy in memory */ + bvdbg("%d. %08x->%08x\n", i, (long)shdr->sh_addr, (long)dest); shdr->sh_addr = (uintptr_t)dest; - bvdbg("%d. 0x%lx %s\n", (long)shdr->sh_addr, loadinfo->secstrings + shdr->sh_name); /* Setup the memory pointer for the next time through the loop */ diff --git a/nuttx/binfmt/libnxflat/Make.defs b/nuttx/binfmt/libnxflat/Make.defs index 4462e9a024..4f522e52b2 100644 --- a/nuttx/binfmt/libnxflat/Make.defs +++ b/nuttx/binfmt/libnxflat/Make.defs @@ -41,7 +41,7 @@ BINFMT_CSRCS += nxflat.c # NXFLAT library -BINFMT_CSRCS = libnxflat_init.c libnxflat_uninit.c libnxflat_load.c \ +BINFMT_CSRCS += libnxflat_init.c libnxflat_uninit.c libnxflat_load.c \ libnxflat_unload.c libnxflat_verify.c libnxflat_read.c \ libnxflat_bind.c diff --git a/nuttx/binfmt/nxflat.c b/nuttx/binfmt/nxflat.c index babc51ff95..8d0ecfdcd9 100644 --- a/nuttx/binfmt/nxflat.c +++ b/nuttx/binfmt/nxflat.c @@ -158,7 +158,7 @@ static int nxflat_loadbinary(struct binary_s *binp) nxflat_dumploadinfo(&loadinfo); if (ret != 0) { - bdbg("Failed to initialize for load of NXFLT program: %d\n", ret); + bdbg("Failed to initialize for load of NXFLAT program: %d\n", ret); goto errout; } @@ -168,7 +168,7 @@ static int nxflat_loadbinary(struct binary_s *binp) nxflat_dumploadinfo(&loadinfo); if (ret != 0) { - bdbg("Failed to load NXFLT program binary: %d\n", ret); + bdbg("Failed to load NXFLAT program binary: %d\n", ret); goto errout_with_init; } diff --git a/nuttx/include/elf.h b/nuttx/include/elf.h index 1b36701fda..c3fb2732d2 100644 --- a/nuttx/include/elf.h +++ b/nuttx/include/elf.h @@ -166,9 +166,9 @@ /* Definitions for Elf32_Sym::st_info */ -#define ELF32_ST_BIND(i) ((i)>>4) -#define ELF32_ST_TYPE(i) ((i)&0xf) -#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xf) +#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf)) /* Figure 4-16: Symbol Binding, ELF32_ST_BIND */ @@ -190,9 +190,9 @@ /* Definitions for Elf32_Rel*::r_info */ -#define ELF32_R_SYM(i) ((i)>>8) -#define ELF32_R_TYPE(i) ((unsigned char)(i)) -#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xff) +#define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff)) /* Figure 5-2: Segment Types, p_type */ diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c index 2d2fff5c56..3e55f50974 100644 --- a/nuttx/tools/mkconfig.c +++ b/nuttx/tools/mkconfig.c @@ -116,7 +116,7 @@ int main(int argc, char **argv, char **envp) printf(" * configured (at present, NXFLAT is the only supported binary.\n"); printf(" * format).\n"); printf(" */\n\n"); - printf("#if !defined(CONFIG_NXFLAT)\n"); + printf("#if !defined(CONFIG_NXFLAT) && !defined(CONFIG_ELF)\n"); printf("# undef CONFIG_BINFMT_DISABLE\n"); printf("# define CONFIG_BINFMT_DISABLE 1\n"); printf("#endif\n\n");