More ELF loader changes

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5261 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-10-25 22:10:56 +00:00
parent 92bbd36612
commit a6e577e3c4
23 changed files with 117 additions and 39 deletions

View File

@ -297,6 +297,53 @@ examples/discover
CONFIG_EXAMPLES_DISCOVER_DRIPADDR - Router IP address CONFIG_EXAMPLES_DISCOVER_DRIPADDR - Router IP address
CONFIG_EXAMPLES_DISCOVER_NETMASK - Network Mask 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 examples/ftpc
^^^^^^^^^^^^^ ^^^^^^^^^^^^^

View File

@ -10,4 +10,20 @@ config EXAMPLES_ELF
Enable the ELF loader example Enable the ELF loader example
if EXAMPLES_ELF 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 endif

View File

@ -61,7 +61,7 @@ ROOTDEPPATH = --dep-path .
VPATH = VPATH =
all: .built all: .built
.PHONY: headers clean depend disclean .PHONY: headers clean_tests clean depend disclean
$(AOBJS): %$(OBJEXT): %.S $(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@) $(call ASSEMBLE, $<, $@)
@ -72,7 +72,7 @@ $(COBJS): %$(OBJEXT): %.c
headers: headers:
@$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) @$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV)
.built: $(OBJS) .built: headers $(OBJS)
@( for obj in $(OBJS) ; do \ @( for obj in $(OBJS) ; do \
$(call ARCHIVE, $(BIN), $${obj}); \ $(call ARCHIVE, $(BIN), $${obj}); \
done ; ) done ; )
@ -88,7 +88,10 @@ context:
depend: .depend depend: .depend
clean: clean_tests:
@$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) clean
clean: clean_tests
@rm -f *.o *~ .*.swp .built @rm -f *.o *~ .*.swp .built
$(call CLEAN) $(call CLEAN)

View File

@ -89,9 +89,16 @@
#define SECTORSIZE 512 #define SECTORSIZE 512
#define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE) #define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE)
#define ROMFSDEV "/dev/ram0"
#define MOUNTPT "/mnt/romfs" #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 /* If CONFIG_DEBUG is enabled, use dbg instead of printf so that the
* output will be synchronous with the debug output. * 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 */ /* Create a ROM disk for the ROMFS filesystem */
message("Registering romdisk\n"); message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR);
ret = romdisk_register(0, romfs_img, NSECTORS(romfs_img_len), SECTORSIZE); ret = romdisk_register(CONFIG_EXAMPLES_ELF_DEVMINOR, romfs_img,
NSECTORS(romfs_img_len), SECTORSIZE);
if (ret < 0) if (ret < 0)
{ {
err("ERROR: romdisk_register failed: %d\n", ret); err("ERROR: romdisk_register failed: %d\n", ret);
@ -178,13 +186,13 @@ int elf_main(int argc, char *argv[])
/* Mount the file system */ /* Mount the file system */
message("Mounting ROMFS filesystem at target=%s with source=%s\n", 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) if (ret < 0)
{ {
err("ERROR: mount(%s,%s,romfs) failed: %s\n", err("ERROR: mount(%s,%s,romfs) failed: %s\n",
ROMFSDEV, MOUNTPT, errno); CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, errno);
elf_uninitialize(); elf_uninitialize();
} }
@ -219,6 +227,6 @@ int elf_main(int argc, char *argv[])
sleep(4); sleep(4);
} }
message("End-of-Test.. Exit-ing\n"); message("End-of-Test.. Exiting\n");
return 0; return 0;
} }

View File

@ -39,7 +39,7 @@
BIN = errno BIN = errno
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -64,7 +64,7 @@ all: $(BIN1) $(BIN2) $(BIN3) $(BIN4)
$(OBJS): %.o: %.cpp $(OBJS): %.o: %.cpp
@echo "CC: $<" @echo "CC: $<"
@$(CXX) -c $(CXXPICFLAGS) $< -o $@ @$(CXX) -c $(CXXFLAGS) $< -o $@
# This contains libstdc++ stubs to that you can build C++ code # This contains libstdc++ stubs to that you can build C++ code
# without actually having libstdc++ # without actually having libstdc++

View File

@ -39,7 +39,7 @@
BIN = hello BIN = hello
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -39,7 +39,7 @@
BIN = longjmp BIN = longjmp
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -39,7 +39,7 @@
BIN = mutex BIN = mutex
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -39,7 +39,7 @@
BIN = pthread BIN = pthread
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -39,7 +39,7 @@
BIN = signal BIN = signal
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -39,7 +39,7 @@
BIN = task BIN = task
SRCS = $(BIN).c SRCS = $(BIN).c
OBJS = $(BIN:.c=.o) OBJS = $(SRCS:.c=.o)
all: $(BIN) all: $(BIN)

View File

@ -644,7 +644,7 @@ ifneq ($(APPDIR),)
fi fi
@$(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" distclean @$(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" distclean
@if [ -r _SAVED_APPS_config ]; then \ @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 ; } \ { echo "Copy of _SAVED_APPS_config failed" ; exit 1 ; } \
fi fi
endif endif

View File

@ -40,7 +40,9 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdlib.h> #include <stdlib.h>
#include <elf.h>
#include <errno.h> #include <errno.h>
#include <debug.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/binfmt/elf.h> #include <nuttx/binfmt/elf.h>
@ -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; 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: case R_386_32:
*ptr += sym->st_value; *ptr += sym->st_value;

View File

@ -40,7 +40,9 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdlib.h> #include <stdlib.h>
#include <elf.h>
#include <errno.h> #include <errno.h>
#include <debug.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/binfmt/elf.h> #include <nuttx/binfmt/elf.h>
@ -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; 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: case R_386_32:
*ptr += sym->st_value; *ptr += sym->st_value;

View File

@ -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_shnum: %d\n", loadinfo->ehdr.e_shnum);
bdbg(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx); 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("Sections %d:\n", i);
bdbg(" sh_name: %08x\n", shdr->sh_name); bdbg(" sh_name: %08x\n", shdr->sh_name);
bdbg(" sh_type: %08x\n", shdr->sh_type); bdbg(" sh_type: %08x\n", shdr->sh_type);
@ -184,7 +184,7 @@ static int elf_loadbinary(struct binary_s *binp)
elf_dumploadinfo(&loadinfo); elf_dumploadinfo(&loadinfo);
if (ret != 0) 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; goto errout;
} }
@ -194,7 +194,7 @@ static int elf_loadbinary(struct binary_s *binp)
elf_dumploadinfo(&loadinfo); elf_dumploadinfo(&loadinfo);
if (ret != 0) 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; goto errout_with_init;
} }

View File

@ -41,7 +41,7 @@ BINFMT_CSRCS += elf.c
# ELF library # 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_unload.c libelf_verify.c libelf_read.c \
libelf_bind.c libelf_symbols.c libelf_bind.c libelf_symbols.c

View File

@ -283,8 +283,8 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
/* Update sh_addr to point to copy in memory */ /* 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; 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 */ /* Setup the memory pointer for the next time through the loop */

View File

@ -41,7 +41,7 @@ BINFMT_CSRCS += nxflat.c
# NXFLAT library # 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_unload.c libnxflat_verify.c libnxflat_read.c \
libnxflat_bind.c libnxflat_bind.c

View File

@ -158,7 +158,7 @@ static int nxflat_loadbinary(struct binary_s *binp)
nxflat_dumploadinfo(&loadinfo); nxflat_dumploadinfo(&loadinfo);
if (ret != 0) 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; goto errout;
} }
@ -168,7 +168,7 @@ static int nxflat_loadbinary(struct binary_s *binp)
nxflat_dumploadinfo(&loadinfo); nxflat_dumploadinfo(&loadinfo);
if (ret != 0) 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; goto errout_with_init;
} }

View File

@ -168,7 +168,7 @@
#define ELF32_ST_BIND(i) ((i) >> 4) #define ELF32_ST_BIND(i) ((i) >> 4)
#define ELF32_ST_TYPE(i) ((i) & 0xf) #define ELF32_ST_TYPE(i) ((i) & 0xf)
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) #define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf))
/* Figure 4-16: Symbol Binding, ELF32_ST_BIND */ /* Figure 4-16: Symbol Binding, ELF32_ST_BIND */
@ -191,8 +191,8 @@
/* Definitions for Elf32_Rel*::r_info */ /* Definitions for Elf32_Rel*::r_info */
#define ELF32_R_SYM(i) ((i) >> 8) #define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i)) #define ELF32_R_TYPE(i) ((i) & 0xff)
#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) #define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff))
/* Figure 5-2: Segment Types, p_type */ /* Figure 5-2: Segment Types, p_type */

View File

@ -116,7 +116,7 @@ int main(int argc, char **argv, char **envp)
printf(" * configured (at present, NXFLAT is the only supported binary.\n"); printf(" * configured (at present, NXFLAT is the only supported binary.\n");
printf(" * format).\n"); printf(" * format).\n");
printf(" */\n\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("# undef CONFIG_BINFMT_DISABLE\n");
printf("# define CONFIG_BINFMT_DISABLE 1\n"); printf("# define CONFIG_BINFMT_DISABLE 1\n");
printf("#endif\n\n"); printf("#endif\n\n");