The ELF loader is basically functional (needs more testing)

git-svn-id: svn://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 f863b72ced
commit 603f1f0317
17 changed files with 247 additions and 269 deletions

View File

@ -383,4 +383,5 @@
* apps/Makefile: Small change that reduces the number of shell invocations
by one (Mike Smith).
* apps/examples/elf: Test example for the ELF loader.
* apps/examples/elf: The ELF module test example appears fully functional.

View File

@ -318,7 +318,12 @@ examples/elf
NOTES:
1. Your top-level nuttx/Make.defs file must include an approproate definition,
1. CFLAGS should be provided in CELFFLAGS. RAM and FLASH memory regions
may require long allcs. For ARM, this might be:
CELFFLAGS = $(CFLAGS) -mlong-calls
2. Your top-level nuttx/Make.defs file must alos 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).
@ -327,24 +332,24 @@ examples/elf
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
3. 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
4. ELF size: The ELF files in this example are, be default, quite large
because they include a lot of "build garbage". You can greatly 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
5. 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.
5. Linker scripts. You might also want to use a linker scripts to combine
6. Linker scripts. You might also want to use a linker scripts to combine
sections better. An example linker script is at nuttx/binfmt/libelf/gnu-elf.ld.
That example might have to be tuned for your particular linker output to
position additional sections correctly. The GNU LD LDELFFLAGS then might

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

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)

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)

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: $<"

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: $<"

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: $<"

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);"

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: $<"

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: $<"

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: $<"

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;

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: $<"

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: $<"

View File

@ -1,6 +1,6 @@
#!/bin/bash
usage="Usage: %0 <test-dir-path>"
usage="Usage: $0 <test-dir-path>"
dir=$1
if [ -z "$dir" ]; then

View File

@ -1,7 +1,7 @@
/****************************************************************************
* examples/nxflat/tests/signal/signal.c
*
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -67,73 +67,41 @@ 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 NXFLAT 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
* pointer to be declared with global scope (at least for ARM). Otherwise,
* a relocation type that is not supported by NXFLAT is generated by GCC.
* 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;
}
/****************************************************************************
@ -147,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",
@ -187,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);
}
@ -212,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;
@ -231,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)
@ -252,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);
}
@ -303,6 +258,7 @@ int main(int argc, char **argv)
fprintf(stderr, "SIGUSR2 not received\n");
exit(10);
}
sigusr2_rcvd = 0;
return 0;