The ELF loader is basically functional (needs more testing)

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5265 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-10-27 00:04:47 +00:00
parent 7bc6a69f46
commit 1f1319f25b
25 changed files with 291 additions and 298 deletions
+21 -15
View File
@@ -39,29 +39,29 @@ include $(APPDIR)/Make.defs
# ELF Example
ASRCS =
CSRCS = elf_main.c
ASRCS =
CSRCS = elf_main.c symtab.c
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
ifeq ($(WINTOOL),y)
BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
else
BIN = "$(APPDIR)/libapps$(LIBEXT)"
BIN = "$(APPDIR)/libapps$(LIBEXT)"
endif
ROOTDEPPATH = --dep-path .
ROOTDEPPATH = --dep-path . --dep-path tests
# Common build
# Build targets
VPATH =
VPATH = tests
all: .built
.PHONY: headers clean_tests clean depend disclean
.PHONY: really_build clean_tests clean depend disclean
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)
@@ -69,15 +69,21 @@ $(AOBJS): %$(OBJEXT): %.S
$(COBJS): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)
headers:
@$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV)
# This is a little messy. The build is broken into two pieces: (1) the
# tests/ subdir build that auto-generates several files, and (2) the real
# build. This is done because we need a fresh build context after auto-
# generating the source files.
.built: headers $(OBJS)
really_build: $(OBJS)
@( for obj in $(OBJS) ; do \
$(call ARCHIVE, $(BIN), $${obj}); \
done ; )
@touch .built
.built:
@$(MAKE) -C tests TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV)
@$(MAKE) TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" really_build
context:
# We can't make dependencies in this directory because the required
+9 -2
View File
@@ -52,10 +52,10 @@
#include <nuttx/ramdisk.h>
#include <nuttx/binfmt/binfmt.h>
#include <nuttx/binfmt/elf.h>
#include <nuttx/binfmt/symtab.h>
#include "tests/romfs.h"
#include "tests/dirlist.h"
#include "tests/symtab.h"
/****************************************************************************
* Definitions
@@ -134,6 +134,13 @@ static const char delimiter[] =
static char path[128];
/****************************************************************************
* Symbols from Auto-Generated Code
****************************************************************************/
extern const struct symtab_s exports[];
extern const int nexports;
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -207,7 +214,7 @@ int elf_main(int argc, char *argv[])
bin.filename = path;
bin.exports = exports;
bin.nexports = NEXPORTS;
bin.nexports = nexports;
ret = load_module(&bin);
if (ret < 0)
+32 -14
View File
@@ -34,35 +34,53 @@
############################################################################
# Most of these do no build yet
SUBDIRS = errno hello hello++ longjmp mutex pthread signal task struct
ALL_SUBDIRS = errno hello hello++ longjmp mutex pthread signal task struct
BUILD_SUBDIRS = errno hello task struct
ifeq ($(CONFIG_HAVE_CXX),y)
BUILD_SUBDIRS += hello++
endif
ifeq ($(CONFIG_EXAMPLES_ELF_LONGJMP),y)
BUILD_SUBDIRS += longjmp
endif
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
BUILD_SUBDIRS += mutex pthread
endif
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
BUILD_SUBDIRS += signal
endif
ELF_DIR = $(APPDIR)/examples/elf
TESTS_DIR = $(ELF_DIR)/tests
ROMFS_DIR = $(TESTS_DIR)/romfs
ROMFS_IMG = $(TESTS_DIR)/romfs.img
ROMFS_HDR = $(TESTS_DIR)/romfs.h
ROMFS_DIRLIST = $(TESTS_DIR)/dirlist.h
SYMTAB = $(TESTS_DIR)/symtab.h
DIRLIST_HDR = $(TESTS_DIR)/dirlist.h
SYMTAB_SRC = $(TESTS_DIR)/symtab.c
define DIR_template
$(1)_$(2):
@$(MAKE) -C $(1) $(3) TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)" CROSSDEV=$(CROSSDEV)
endef
all: $(ROMFS_HDR) $(ROMFS_DIRLIST) $(SYMTAB)
all: $(ROMFS_HDR) $(DIRLIST_HDR) $(SYMTAB_SRC)
.PHONY: all build clean install populate
$(foreach DIR, $(SUBDIRS), $(eval $(call DIR_template,$(DIR),build, all)))
$(foreach DIR, $(SUBDIRS), $(eval $(call DIR_template,$(DIR),clean,clean)))
$(foreach DIR, $(SUBDIRS), $(eval $(call DIR_template,$(DIR),install,install)))
$(foreach DIR, $(BUILD_SUBDIRS), $(eval $(call DIR_template,$(DIR),build, all)))
$(foreach DIR, $(ALL_SUBDIRS), $(eval $(call DIR_template,$(DIR),clean,clean)))
$(foreach DIR, $(BUILD_SUBDIRS), $(eval $(call DIR_template,$(DIR),install,install)))
# Build program(s) in each sud-directory
build: $(foreach DIR, $(SUBDIRS), $(DIR)_build)
build: $(foreach DIR, $(BUILD_SUBDIRS), $(DIR)_build)
# Install each program in the romfs directory
install: $(foreach DIR, $(SUBDIRS), $(DIR)_install)
install: $(foreach DIR, $(BUILD_SUBDIRS), $(DIR)_install)
# Create the romfs directory
@@ -85,16 +103,16 @@ $(ROMFS_HDR) : $(ROMFS_IMG)
# Create the dirlist.h header file from the romfs directory
$(ROMFS_DIRLIST) : populate
$(DIRLIST_HDR) : populate
@$(TESTS_DIR)/mkdirlist.sh $(ROMFS_DIR) >$@
# Create the exported symbol table list from the derived *-thunk.S files
$(SYMTAB): build
@$(TESTS_DIR)/mksymtab.sh $(TESTS_DIR) >$@
$(SYMTAB_SRC): build
@$(TESTS_DIR)/mksymtab.sh -t varlist.tmp $(ROMFS_DIR) >$@
# Clean each subdirectory
clean: $(foreach DIR, $(SUBDIRS), $(DIR)_clean)
@rm -f $(ROMFS_HDR) $(ROMFS_IMG) $(SYMTAB)
clean: $(foreach DIR, $(ALL_SUBDIRS), $(DIR)_clean)
@rm -f $(ROMFS_HDR) $(ROMFS_IMG) $(SYMTAB_SRC) varlist.tmp
@rm -rf $(ROMFS_DIR)
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+39 -11
View File
@@ -1,6 +1,24 @@
#!/bin/bash
usage="Usage: %0 <test-dir-path>"
usage="Usage: $0 [-t <tmp-file>] <test-dir-path>"
# Check for the optional tempory file name
tmpfile=varlist.tmp
if [ "X${1}" = "X-t" ]; then
shift
tmpfile=$1
shift
if [ -z "$tmpfile" ]; then
echo "ERROR: Missing <tmpfile>"
echo ""
echo $usage
exit 1
fi
fi
# Check for the required ROMFS directory path
dir=$1
if [ -z "$dir" ]; then
@@ -17,23 +35,33 @@ if [ ! -d "$dir" ]; then
exit 1
fi
varlist=`find $dir -name "*-thunk.S"| xargs grep -h asciz | cut -f3 | sort | uniq`
# Extract all of the undefined symbols from the ELF files and create a
# list of sorted, unique undefined variable names.
echo "#ifndef __EXAMPLES_ELF_TESTS_SYMTAB_H"
echo "#define __EXAMPLES_ELF_TESTS_SYMTAB_H"
echo ""
varlist=`find ${dir} -executable -type f | xargs nm | fgrep ' U ' | sed -e "s/^[ ]*//g" | cut -d' ' -f2 | sort | uniq`
# Now output the symbol table as a structure in a C source file. All
# undefined symbols are declared as void* types. If the toolchain does
# any kind of checking for function vs. data objects, then this could
# faile
echo "#include <nuttx/compiler.h>"
echo "#include <nuttx/binfmt/symtab.h>"
echo ""
echo "static const struct symtab_s exports[] = "
for var in $varlist; do
echo "extern void *${var};"
done
echo ""
echo "const struct symtab_s exports[] = "
echo "{"
for string in $varlist; do
var=`echo $string | sed -e "s/\"//g"`
echo " {$string, $var},"
for var in $varlist; do
echo " {\"${var}\", &${var}},"
done
echo "};"
echo "#define NEXPORTS (sizeof(exports)/sizeof(struct symtab_s))"
echo ""
echo "#endif /* __EXAMPLES_ELF_TESTS_SYMTAB_H */"
echo "const int nexports = sizeof(exports) / sizeof(struct symtab_s);"
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+62 -105
View File
@@ -38,6 +38,7 @@
****************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
@@ -66,22 +67,7 @@ static int sigusr2_rcvd = 0;
****************************************************************************/
/****************************************************************************
* Name: sigusr1_sighandler
****************************************************************************/
/* NOTE: it is necessary for functions that are referred to by function pointers
* pointer to be declared with global scope (at least for ARM). Otherwise,
* a relocation type that is not supported by ELF is generated by GCC.
*/
void sigusr1_sighandler(int signo)
{
printf("sigusr1_sighandler: Received SIGUSR1, signo=%d\n", signo);
sigusr1_rcvd = 1;
}
/****************************************************************************
* Name: sigusr2_sigaction
* Name: siguser_action
***************************************************************************/
/* NOTE: it is necessary for functions that are referred to by function pointers
@@ -89,50 +75,33 @@ void sigusr1_sighandler(int signo)
* a relocation type that is not supported by ELF is generated by GCC.
*/
#ifdef __USE_POSIX199309
void sigusr2_sigaction(int signo, siginfo_t *siginfo, void *arg)
void siguser_action(int signo, siginfo_t *siginfo, void *arg)
{
printf("sigusr2_sigaction: Received SIGUSR2, signo=%d siginfo=%p arg=%p\n",
printf("siguser_action: Received signo=%d siginfo=%p arg=%p\n",
signo, siginfo, arg);
#ifdef HAVE_SIGQUEUE
if (signo == SIGUSR1)
{
printf(" SIGUSR1 received\n");
sigusr2_rcvd = 1;
}
else if (signo == SIGUSR2)
{
printf(" SIGUSR2 received\n");
sigusr1_rcvd = 2;
}
else
{
printf(" ERROR: Unexpected signal\n");
}
if (siginfo)
{
printf("siginfo:\n");
printf(" si_signo = %d\n", siginfo->si_signo);
printf(" si_errno = %d\n", siginfo->si_errno);
printf(" si_code = %d\n", siginfo->si_code);
printf(" si_pid = %d\n", siginfo->si_pid);
printf(" si_uid = %d\n", siginfo->si_uid);
printf(" si_status = %d\n", siginfo->si_status);
printf(" si_utime = %ld\n", (long)siginfo->si_utime);
printf(" si_stime = %ld\n", (long)siginfo->si_stime);
printf(" si_value = %d\n", siginfo->si_value.sival_int);
printf(" si_int = %d\n", siginfo->si_int);
printf(" si_ptr = %p\n", siginfo->si_ptr);
printf(" si_addr = %p\n", siginfo->si_addr);
printf(" si_band = %ld\n", siginfo->si_band);
printf(" si_fd = %d\n", siginfo->si_fd);
}
#endif
sigusr2_rcvd = 1;
}
#else
void sigusr2_sigaction(int signo)
{
printf("sigusr2_sigaction: Received SIGUSR2, signo=%d\n", signo);
sigusr2_rcvd = 1;
}
#endif
/****************************************************************************
* Name: sigusr2_sighandler
****************************************************************************/
static void sigusr2_sighandler(int signo)
{
printf("sigusr2_sighandler: Received SIGUSR2, signo=%d\n", signo);
sigusr2_rcvd = 1;
}
/****************************************************************************
@@ -146,39 +115,36 @@ static void sigusr2_sighandler(int signo)
int main(int argc, char **argv)
{
struct sigaction act;
struct sigaction oact;
void (*old_sigusr1_sighandler)(int signo);
void (*old_sigusr2_sighandler)(int signo);
struct sigaction oact1;
struct sigaction oact2;
pid_t mypid = getpid();
#if defined(__USE_POSIX199309) && defined(HAVE_SIGQUEUE)
sigval_t sigval;
#endif
union sigval sigval;
int status;
printf("Setting up signal handlers from pid=%d\n", mypid);
/* Set up so that sigusr1_sighandler will respond to SIGUSR1 */
old_sigusr1_sighandler = signal(SIGUSR1, sigusr1_sighandler);
if (old_sigusr1_sighandler == SIG_ERR)
{
fprintf(stderr, "Failed to install SIGUSR1 handler, errno=%d\n",
errno);
exit(1);
}
printf("Old SIGUSR1 sighandler at %p\n", old_sigusr1_sighandler);
printf("New SIGUSR1 sighandler at %p\n", sigusr1_sighandler);
/* Set up so that sigusr2_sigaction will respond to SIGUSR2 */
/* Set up so that siguser_action will respond to SIGUSR1 */
memset(&act, 0, sizeof(struct sigaction));
act.sa_sigaction = sigusr2_sigaction;
act.sa_sigaction = siguser_action;
act.sa_flags = SA_SIGINFO;
(void)sigemptyset(&act.sa_mask);
status = sigaction(SIGUSR2, &act, &oact);
status = sigaction(SIGUSR1, &act, &oact1);
if (status != 0)
{
fprintf(stderr, "Failed to install SIGUSR1 handler, errno=%d\n",
errno);
exit(2);
}
printf("Old SIGUSR1 sighandler at %p\n", oact1.sa_handler);
printf("New SIGUSR1 sighandler at %p\n", siguser_action);
/* Set up so that siguser_action will respond to SIGUSR2 */
status = sigaction(SIGUSR2, &act, &oact2);
if (status != 0)
{
fprintf(stderr, "Failed to install SIGUSR2 handler, errno=%d\n",
@@ -186,18 +152,19 @@ int main(int argc, char **argv)
exit(2);
}
printf("Old SIGUSR2 sighandler at %p\n", oact.sa_handler);
printf("New SIGUSR2 sighandler at %p\n", sigusr2_sigaction);
printf("Raising SIGUSR1 from pid=%d\n", mypid);
printf("Old SIGUSR2 sighandler at %p\n", oact2.sa_handler);
printf("New SIGUSR2 sighandler at %p\n", siguser_action);
printf("Raising SIGUSR1 from pid=%d\n", mypid);
fflush(stdout); usleep(SHORT_DELAY);
/* Send SIGUSR1 to ourselves via raise() */
/* Send SIGUSR1 to ourselves via kill() */
status = raise(SIGUSR1);
printf("Kill-ing SIGUSR1 from pid=%d\n", mypid);
status = kill(0, SIGUSR1);
if (status != 0)
{
fprintf(stderr, "Failed to raise SIGUSR1, errno=%d\n", errno);
fprintf(stderr, "Failed to kill SIGUSR1, errno=%d\n", errno);
exit(3);
}
@@ -211,14 +178,14 @@ int main(int argc, char **argv)
fprintf(stderr, "SIGUSR1 not received\n");
exit(4);
}
sigusr1_rcvd = 0;
/* Send SIGUSR2 to ourselves */
printf("Killing SIGUSR2 from pid=%d\n", mypid);
printf("sigqueue-ing SIGUSR2 from pid=%d\n", mypid);
fflush(stdout); usleep(SHORT_DELAY);
#if defined(__USE_POSIX199309) && defined(HAVE_SIGQUEUE)
/* Send SIGUSR2 to ourselves via sigqueue() */
sigval.sival_int = 87;
@@ -230,20 +197,8 @@ int main(int argc, char **argv)
}
usleep(SHORT_DELAY);
printf("SIGUSR2 queued from pid=%d, sigval=97\n", mypid);
#else
/* Send SIGUSR2 to ourselves via kill() */
printf("SIGUSR2 queued from pid=%d, sigval=87\n", mypid);
status = kill(mypid, SIGUSR2);
if (status != 0)
{
fprintf(stderr, "Failed to kill SIGUSR2, errno=%d\n", errno);
exit(5);
}
usleep(SHORT_DELAY);
printf("SIGUSR2 killed from pid=%d\n", mypid);
#endif
/* Verify that SIGUSR2 was received */
if (sigusr2_rcvd == 0)
@@ -251,32 +206,33 @@ int main(int argc, char **argv)
fprintf(stderr, "SIGUSR2 not received\n");
exit(6);
}
sigusr2_rcvd = 0;
/* Remove the sigusr2_sigaction handler and replace the SIGUSR2
/* Remove the siguser_action handler and replace the SIGUSR2
* handler with sigusr2_sighandler.
*/
printf("Resetting SIGUSR2 signal handler from pid=%d\n", mypid);
old_sigusr2_sighandler = signal(SIGUSR2, sigusr2_sighandler);
if (old_sigusr2_sighandler == SIG_ERR)
status = sigaction(SIGUSR2, &oact2, &act);
if (status != 0)
{
fprintf(stderr, "Failed to install SIGUSR2 handler, errno=%d\n",
fprintf(stderr, "Failed to install SIGUSR1 handler, errno=%d\n",
errno);
exit(7);
exit(2);
}
printf("Old SIGUSR2 sighandler at %p\n", old_sigusr2_sighandler);
printf("New SIGUSR2 sighandler at %p\n", sigusr2_sighandler);
printf("Old SIGUSR1 sighandler at %p\n", act.sa_handler);
printf("New SIGUSR1 sighandler at %p\n", oact1.sa_handler);
/* Verify that the handler that was removed was sigusr2_sigaction */
/* Verify that the handler that was removed was siguser_action */
if ((void*)old_sigusr2_sighandler != (void*)sigusr2_sigaction)
if ((void*)act.sa_handler != (void*)siguser_action)
{
fprintf(stderr,
"Old SIGUSR2 signhanlder (%p) is not sigusr2_sigation (%p)\n",
old_sigusr2_sighandler, sigusr2_sigaction);
"Old SIGUSR2 signal handler (%p) is not siguser_action (%p)\n",
act.sa_handler, siguser_action);
exit(8);
}
@@ -302,6 +258,7 @@ int main(int argc, char **argv)
fprintf(stderr, "SIGUSR2 not received\n");
exit(10);
}
sigusr2_rcvd = 0;
return 0;
+2 -2
View File
@@ -36,7 +36,7 @@
-include $(TOPDIR)/.config
-include $(TOPDIR)/Make.defs
CFLAGS += -I.
CELFFLAGS += -I.
BIN = struct
SRCS = struct_main.c struct_dummy.c
@@ -46,7 +46,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"
+1 -1
View File
@@ -45,7 +45,7 @@ all: $(BIN)
$(OBJS): %.o: %.c
@echo "CC: $<"
@$(CC) -c $(CFLAGS) $< -o $@
@$(CC) -c $(CELFFLAGS) $< -o $@
$(BIN): $(OBJS)
@echo "LD: $<"