diff --git a/examples/README.txt b/examples/README.txt index e6229dc63..1040e6f80 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -774,10 +774,10 @@ examples/mm examples/module ^^^^^^^^^^^^^^ - This example builds a small loadable module test case. This includes on + This example builds a small loadable module test case. This includes a character driver under examples/module/drivers. This driver is built using the relocatable ELF format and installed in a ROMFS file system. At run time, - the driver module is loaded and exercises. Requires CONFIG_MODULE. + the driver module is loaded and exercised. Requires CONFIG_MODULE. Other configuration options: CONFIG_EXAMPLES_ELF_DEVMINOR - The minor device number of the ROMFS block @@ -792,18 +792,18 @@ examples/module NOTES: - 1. CFLAGS should be provided in CELFFLAGS. RAM and FLASH memory regions + 1. CFLAGS should be provided in CMODULEFLAGS. RAM and FLASH memory regions may require long allcs. For ARM, this might be: - CELFFLAGS = $(CFLAGS) -mlong-calls + CMODULEFLAGS = $(CFLAGS) -mlong-calls - Similarly for C++ flags which must be provided in CXXELFFLAGS. + Similarly for C++ flags which must be provided in CXXMODULEFLAGS. 2. Your top-level nuttx/Make.defs file must also include an approproate definition, - LDELFFLAGS, to generate a relocatable ELF object. With GNU LD, this should + LDMODULEFLAGS, to generate a relocatable ELF object. With GNU LD, this should include '-r' and '-e '. - LDELFFLAGS = -r -e module_initialize + LDMODULEFLAGS = -r -e module_initialize If you use GCC to link, you make also need to include '-nostdlib' or '-nostartfiles' and '-nodefaultlibs'. @@ -828,10 +828,10 @@ examples/module 6. Linker scripts. You might also want to use a linker scripts to combine sections better. An example linker script is at nuttx/sched/module/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 + position additional sections correctly. The GNU LD LDMODULEFLAGS then might be: - LDELFFLAGS = -r -e module_initialize -T$(TOPDIR)/sched/module/gnu-elf.ld + LDMODULEFLAGS = -r -e module_initialize -T$(TOPDIR)/sched/module/gnu-elf.ld examples/modbus ^^^^^^^^^^^^^^^ @@ -1855,6 +1855,66 @@ examples/smp This is a simple test for SMP functionality. It is basically just the pthread barrier test with some custom instrumentation. +examples/sotest +^^^^^^^^^^^^^^^ + + This example builds a small shared library module test case. The test + shared library is built using the relocatable ELF format and installed + in a ROMFS file system. At run time, the shared library is installed and exercised. Requires CONFIG_LIBC_DLLFCN. Other configuration options: + + CONFIG_EXAMPLES_SOTEST_DEVMINOR - The minor device number of the ROMFS block + driver. 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_SOTEST_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. CFLAGS should be provided in CMODULEFLAGS. RAM and FLASH memory regions + may require long allcs. For ARM, this might be: + + CMODULEFLAGS = $(CFLAGS) -mlong-calls + + Similarly for C++ flags which must be provided in CXXMODULEFLAGS. + + 2. Your top-level nuttx/Make.defs file must also include an approproate definition, + LDMODULEFLAGS, to generate a relocatable ELF object. With GNU LD, this should + include '-r' and '-e '. + + LDMODULEFLAGS = -r -e module_initialize + + If you use GCC to link, you make also need to include '-nostdlib' or + '-nostartfiles' and '-nodefaultlibs'. + + 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 + in the NuttX tools repository (genromfs-0.5.2.tar.gz). In any event, the + PATH variable must include the path to the genromfs executable. + + 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. + + 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. + + 6. Linker scripts. You might also want to use a linker scripts to combine + sections better. An example linker script is at nuttx/sched/module/gnu-elf.ld. + That example might have to be tuned for your particular linker output to + position additional sections correctly. The GNU LD LDMODULEFLAGS then might + be: + + LDMODULEFLAGS = -r -e module_initialize -T$(TOPDIR)/sched/module/gnu-elf.ld + examples/system ^^^^^^^^^^^^^^^ diff --git a/examples/sotest/.gitignore b/examples/sotest/.gitignore new file mode 100644 index 000000000..4cfc495be --- /dev/null +++ b/examples/sotest/.gitignore @@ -0,0 +1,3 @@ +/Make.dep +/.depend +/.built diff --git a/examples/sotest/Kconfig b/examples/sotest/Kconfig new file mode 100644 index 000000000..14b578e81 --- /dev/null +++ b/examples/sotest/Kconfig @@ -0,0 +1,55 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_SOTEST + bool "Shared Library Example" + default n + depends on LIBC_DLLFCN + ---help--- + Enable the shared library example + +if EXAMPLES_SOTEST + +config EXAMPLES_SOTEST_LIBC + bool "Link with LIBC" + default n + depends on !BUILD_KERNEL && EXPERIMENTAL + ---help--- + Link with the C library (and also math library if it was built). + By default, all undefined symbols must be provided via a symbol + table. But if this option is selected, then each SOTEST test program + will link with the SYSCALL library and will interface with the OS + system calls. You probably will NOT want this option, however, + because it will substantially increase the size of code. For + example, a separate copy of printf() would be linked with every + program greatly increasing the total code size. This option is + primarily intended only for testing. + + WARNING: Libc will not be built with -mlong-calls and this may + result in runtime linking failures due to out-of-range functions + calls. + +config EXAMPLES_SOTEST_LIBGCC + bool "Link with LIBGCC" + default n + depends on !BUILD_KERNEL && EXPERIMENTAL + +config EXAMPLES_SOTEST_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 SOTEST executables to be tested. Default: 0 + +config EXAMPLES_SOTEST_DEVPATH + string "ROMFS Device Path" + default "/dev/ram0" + ---help--- + The path to the ROMFS block driver device. This must match EXAMPLES_SOTEST_DEVMINOR. + Used for registering the RAM block driver that will hold the ROMFS file system + containing the SOTEST executables to be tested. Default: "/dev/ram0" + +endif diff --git a/examples/sotest/Make.defs b/examples/sotest/Make.defs new file mode 100644 index 000000000..960b3ef55 --- /dev/null +++ b/examples/sotest/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# apps/examples/sotest/Make.defs +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_EXAMPLES_SOTEST),y) +CONFIGURED_APPS += examples/sotest +endif diff --git a/examples/sotest/Makefile b/examples/sotest/Makefile new file mode 100644 index 000000000..a0cca4352 --- /dev/null +++ b/examples/sotest/Makefile @@ -0,0 +1,157 @@ +############################################################################ +# apps/examples/sotest/Makefile +# +# Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs + +OBJEXT ?= .o +DELIM ?= / + +include $(APPDIR)/Make.defs + +# Shared library example built-in application info + +APPNAME = sotest +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +# Shared Library Example + +ASRCS = +CSRCS = symtab.c +MAINSRC = sotest_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +MAINOBJ = $(MAINSRC:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(MAINSRC) +OBJS = $(AOBJS) $(COBJS) + +ifneq ($(CONFIG_BUILD_KERNEL),y) + OBJS += $(MAINOBJ) +endif + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ifeq ($(WINTOOL),y) + INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}" +else + INSTALL_DIR = $(BIN_DIR) +endif + +CONFIG_XYZ_PROGNAME ?= discover$(EXEEXT) +PROGNAME = $(CONFIG_XYZ_PROGNAME) + +ROOTDEPPATH = --dep-path . --dep-path lib + +# Build targets + +VPATH = lib + +all: .built +.PHONY: really_build clean_lib clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +# This is a little messy. The build is broken into two pieces: (1) the +# lib/ 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. + +really_build: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + @touch .built + +.built: + @$(MAKE) -C lib TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) + @$(MAKE) TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" really_build + +ifeq ($(CONFIG_BUILD_KERNEL),y) +$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) + @echo "LD: $(PROGNAME)" + $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) + $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) + +install: $(BIN_DIR)$(DELIM)$(PROGNAME) + +else +install: + +endif + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + +context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat +else +context: +endif + +# We can't make dependencies in this directory because the required +# header files may not yet exist. + +.depend: + @touch $@ + +depend: .depend + +clean_lib: + @$(MAKE) -C lib TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" CROSSDEV=$(CROSSDEV) clean + +clean: clean_lib + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep +.PHONY: preconfig +preconfig: diff --git a/examples/sotest/lib/.gitignore b/examples/sotest/lib/.gitignore new file mode 100644 index 000000000..23504a6af --- /dev/null +++ b/examples/sotest/lib/.gitignore @@ -0,0 +1,5 @@ +/romfs +/romfs.h +/romfs.img +/symtab.c + diff --git a/examples/sotest/lib/Makefile b/examples/sotest/lib/Makefile new file mode 100644 index 000000000..36e8193f4 --- /dev/null +++ b/examples/sotest/lib/Makefile @@ -0,0 +1,98 @@ +############################################################################ +# apps/examples/sotest/lib/Makefile +# +# Copyright (C) 2015 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +ALL_SUBDIRS = sotest +BUILD_SUBDIRS = sotest + +SOTEST_DIR = $(APPDIR)/examples/sotest +LIB_DIR = $(SOTEST_DIR)/lib +ROMFS_DIR = $(LIB_DIR)/romfs +ROMFS_IMG = $(LIB_DIR)/romfs.img +ROMFS_HDR = $(LIB_DIR)/romfs.h +SYMTAB_SRC = $(LIB_DIR)/symtab.c + +define DIR_template +$(1)_$(2): + $(Q) $(MAKE) -C $(1) $(3) TOPDIR="$(TOPDIR)" APPDIR="$(APPDIR)" ROMFS_DIR="$(ROMFS_DIR)" CROSSDEV=$(CROSSDEV) +endef + +all: $(ROMFS_HDR) $(DIRLIST_HDR) $(SYMTAB_SRC) +.PHONY: all build clean install populate + +$(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, $(BUILD_SUBDIRS), $(DIR)_build) + +# Install each program in the romfs directory + +install: $(foreach DIR, $(BUILD_SUBDIRS), $(DIR)_install) + +# Create the romfs directory + +$(ROMFS_DIR): + $(Q) mkdir $(ROMFS_DIR) + +# Populate the romfs directory + +populate: $(ROMFS_DIR) build install + +# Create the romfs.img file from the populated romfs directory + +$(ROMFS_IMG): populate + $(Q) genromfs -f $@ -d $(ROMFS_DIR) -V "SOTESTTEST" + +# Create the romfs.h header file from the romfs.img file + +$(ROMFS_HDR) : $(ROMFS_IMG) + $(Q) (cd $(LIB_DIR); xxd -i romfs.img | sed -e "s/^unsigned/static const unsigned/g" >$@) + +# Create the exported symbol table + +$(SYMTAB_SRC): build + $(Q) $(LIB_DIR)/mksymtab.sh $(ROMFS_DIR) >$@ + +# Clean each subdirectory + +clean: $(foreach DIR, $(ALL_SUBDIRS), $(DIR)_clean) + $(Q) rm -f $(ROMFS_HDR) $(DIRLIST_HDR) $(ROMFS_IMG) $(SYMTAB_SRC) + $(Q) rm -rf $(ROMFS_DIR) diff --git a/examples/sotest/lib/mksymtab.sh b/examples/sotest/lib/mksymtab.sh new file mode 100644 index 000000000..1c26d82aa --- /dev/null +++ b/examples/sotest/lib/mksymtab.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +usage="Usage: $0 " + +# Check for the required ROMFS directory path + +dir=$1 +if [ -z "$dir" ]; then + echo "ERROR: Missing " + echo "" + echo $usage + exit 1 +fi + +if [ ! -d "$dir" ]; then + echo "ERROR: Directory $dir does not exist" + echo "" + echo $usage + exit 1 +fi + +# Extract all of the undefined symbols from the SOTEST files and create a +# list of sorted, unique undefined variable names. + +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 " +echo "#include " +echo "" + +for var in $varlist; do + echo "extern void *${var};" +done + +echo "" +echo "const struct symtab_s exports[] = " +echo "{" + +for var in $varlist; do + echo " {\"${var}\", &${var}}," +done + +echo "};" +echo "" +echo "const int nexports = sizeof(exports) / sizeof(struct symtab_s);" + diff --git a/examples/sotest/lib/sotest/.gitignore b/examples/sotest/lib/sotest/.gitignore new file mode 100644 index 000000000..87ef4567e --- /dev/null +++ b/examples/sotest/lib/sotest/.gitignore @@ -0,0 +1,2 @@ +/sotest + diff --git a/examples/sotest/lib/sotest/Makefile b/examples/sotest/lib/sotest/Makefile new file mode 100644 index 000000000..216f6e202 --- /dev/null +++ b/examples/sotest/lib/sotest/Makefile @@ -0,0 +1,94 @@ +############################################################################ +# examples/sotest/lib/sotest/Makefile +# +# Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +OBJEXT ?= .o +DELIM ?= / + +ifeq ($(WINTOOL),y) +NUTTXLIB = "${shell cygpath -w $(TOPDIR)$(DELIM)lib}" +else +NUTTXLIB = "$(TOPDIR)$(DELIM)lib" +endif + +KDEFINE = ${shell $(TOPDIR)/tools/define.sh "$(CC)" __KERNEL__} +CMODULEFLAGS += $(KDEFINE) + +ifeq ($(CONFIG_EXAMPLES_SOTEST_LIBGCC),y) +LIBGCC = "${shell $(CC) $(ARCHCPUFLAGS) -print-libgcc-file-name 2>/dev/null}" +ifneq ($(LIBGCC),) + LDLIBPATH += -L "${shell dirname $(LIBGCC)}" + LDLIBS += -lgcc +endif +endif + +ifeq ($(CONFIG_EXAMPLES_SOTEST_LIBC),y) +LDMODULEFLAGS += -Bstatic +LDLIBPATH += -L $(NUTTXLIB) +endif + +ifeq ($(CONFIG_EXAMPLES_SOTEST_LIBC),y) +ifeq ($(CONFIG_BUILD_PROTECTED),y) +LDLIBS += -luc +else +LDLIBS += -lc +endif +endif + +BIN = sotest + +SRCS = $(BIN).c +OBJS = $(SRCS:.c=$(OBJEXT)) + +all: $(BIN) +.PHONY: clean install + +$(OBJS): %$(OBJEXT): %.c + @echo "CC: $<" + $(Q) $(CC) -c $(CMODULEFLAGS) $< -o $@ + +$(BIN): $(OBJS) + @echo "LD: $<" + $(Q) $(LD) $(LDMODULEFLAGS) $(LDLIBPATH) -o $@ $(ARCHCRT0OBJ) $^ $(LDLIBS) + +clean: + $(call DELFILE, $(BIN)) + $(call CLEAN) + +install: + $(Q) mkdir -p $(ROMFS_DIR) + $(Q) install $(BIN) $(ROMFS_DIR)/$(BIN) diff --git a/examples/sotest/lib/sotest/sotest.c b/examples/sotest/lib/sotest/sotest.c new file mode 100644 index 000000000..ce9332d49 --- /dev/null +++ b/examples/sotest/lib/sotest/sotest.c @@ -0,0 +1,161 @@ +/**************************************************************************** + * apps/examples/sotest/libs/sotest/sotest.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private data + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void testfunc1(FAR const char *msg); +static void testfunc2(FAR const char *msg); +static void testfunc3(FAR const char *msg); +static int module_uninitialize(FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_msg1[] = "Hello to you too!"; +static const char g_msg2[] = "Not so bad so far."; +static const char g_msg3[] = "Yes, don't be a stranger!"; + +static const struct symtab_s g_exports[6] = +{ + { + (FAR const char *)"testfunc1", (FAR const void *)testfunc1, + }, + { + (FAR const char *)"testfunc2", (FAR const void *)testfunc2, + }, + { + (FAR const char *)"testfunc3", (FAR const void *)testfunc3, + }, + { + (FAR const char *)"g_msg1", (FAR const void *)g_msg1, + }, + { + (FAR const char *)"g_msg2", (FAR const void *)g_msg2, + }, + { + (FAR const char *)"g_msg3", (FAR const void *)g_msg3, + }, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: testfunc1 + ****************************************************************************/ + +static void testfunc1(FAR const char *msg) +{ + syslog(LOG_INFO, "testfunc1: Hello, everyone!\n"); + syslog(LOG_INFO, " caller: %s\n", msg); +} + +/**************************************************************************** + * Name: testfunc2 + ****************************************************************************/ + +static void testfunc2(FAR const char *msg) +{ + syslog(LOG_INFO, "testfunc2: Hope you are having a great day!\n"); + syslog(LOG_INFO, " caller: %s\n", msg); +} + +/**************************************************************************** + * Name: testfunc3 + ****************************************************************************/ + +static void testfunc3(FAR const char *msg) +{ + syslog(LOG_INFO, "testfunc3: Let's talk again very soon\n"); + syslog(LOG_INFO, " caller: %s\n", msg); +} + +/**************************************************************************** + * Name: module_uninitialize + ****************************************************************************/ + +static int module_uninitialize(FAR void *arg) +{ + syslog(LOG_INFO, "module_uninitialize: arg=%p\n", arg); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: module_initialize + * + * Description: + * Register /dev/sotest + * + ****************************************************************************/ + +int module_initialize(FAR struct mod_info_s *modinfo) +{ + syslog(LOG_INFO, "module_initialize:\n"); + + modinfo->uninitializer = module_uninitialize; + modinfo->arg = NULL; + modinfo->exports = g_exports; + modinfo->nexports = 6; + + return OK; +} diff --git a/examples/sotest/sotest_main.c b/examples/sotest/sotest_main.c new file mode 100644 index 000000000..b40614bbf --- /dev/null +++ b/examples/sotest/sotest_main.c @@ -0,0 +1,247 @@ +/**************************************************************************** + * examples/sotest/sotest_main.c + * + * Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "lib/romfs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Check configuration. This is not all of the configuration settings that + * are required -- only the more obvious. + */ + +#ifndef CONFIG_LIBC_DLLFCN +# error "You must select CONFIG_LIBC_DLLFCN in your configuration file" +#endif + +#ifndef CONFIG_FS_ROMFS +# error "You must select CONFIG_FS_ROMFS in your configuration file" +#endif + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# error "You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file" +#endif + +/* Describe the ROMFS file system */ + +#define SECTORSIZE 64 +#define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE) +#define MOUNTPT "/mnt/romfs" + +#ifndef CONFIG_EXAMPLES_SOTEST_DEVMINOR +# define CONFIG_EXAMPLES_SOTEST_DEVMINOR 0 +#endif + +#ifndef CONFIG_EXAMPLES_SOTEST_DEVPATH +# define CONFIG_EXAMPLES_SOTEST_DEVPATH "/dev/ram0" +#endif + +/**************************************************************************** + * Private data + ****************************************************************************/ + +/**************************************************************************** + * Symbols from Auto-Generated Code + ****************************************************************************/ + +extern const struct symtab_s exports[]; +extern const int nexports; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sotest_main + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int sotest_main(int argc, char *argv[]) +#endif +{ + FAR void *handle; + CODE void (*testfunc)(FAR const char *msg); + FAR const char *msg; + int ret; + + /* Set the shared library symbol table */ + + ret = dlsymtab((FAR struct symtab_s *)exports, nexports); + if (ret < 0) + { + fprintf(stderr, "ERROR: dlsymtab failed: %d\n", ret); + exit(EXIT_FAILURE); + } + + /* Create a ROM disk for the ROMFS filesystem */ + + printf("main: Registering romdisk at /dev/ram%d\n", + CONFIG_EXAMPLES_SOTEST_DEVMINOR); + + ret = romdisk_register(CONFIG_EXAMPLES_SOTEST_DEVMINOR, + (FAR uint8_t *)romfs_img, + NSECTORS(romfs_img_len), SECTORSIZE); + if (ret < 0) + { + /* This will happen naturally if we registered the ROM disk previously. */ + + if (ret != -EEXIST) + { + fprintf(stderr, "ERROR: romdisk_register failed: %d\n", ret); + exit(EXIT_FAILURE); + } + + printf("main: ROM disk already registered\n"); + } + + /* Mount the file system */ + + printf("main: Mounting ROMFS filesystem at target=%s with source=%s\n", + MOUNTPT, CONFIG_EXAMPLES_SOTEST_DEVPATH); + + ret = mount(CONFIG_EXAMPLES_SOTEST_DEVPATH, MOUNTPT, "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + fprintf(stderr, "ERROR: mount(%s,%s,romfs) failed: %s\n", + CONFIG_EXAMPLES_SOTEST_DEVPATH, MOUNTPT, errno); + exit(EXIT_FAILURE); + } + + /* Install the test shared library */ + + handle = dlopen(MOUNTPT "/sotest", RTLD_NOW | RTLD_LOCAL); + if (handle == NULL) + { + fprintf(stderr, "ERROR: dlopen failed\n"); + exit(EXIT_FAILURE); + } + + /* Get symbols testfunc1 and msg1 */ + + testfunc = (CODE void (*)(FAR const char *))dlsym(handle, "testfunc1"); + if (testfunc == NULL) + { + fprintf(stderr, "ERROR: Failed to get symbol \"testfunc1\"\n"); + exit(EXIT_FAILURE); + } + + msg = (FAR const char *)dlsym(handle, "g_msg1"); + if (msg == NULL) + { + fprintf(stderr, "ERROR: Failed to get symbol \"g_msg1\"\n"); + exit(EXIT_FAILURE); + } + + /* Execute testfunc1 */ + + testfunc(msg); + + /* Get symbols testfunc2 and msg2 */ + + testfunc = (CODE void (*)(FAR const char *))dlsym(handle, "testfunc2"); + if (testfunc == NULL) + { + fprintf(stderr, "ERROR: Failed to get symbol \"testfunc2\"\n"); + exit(EXIT_FAILURE); + } + + msg = (FAR const char *)dlsym(handle, "g_msg2"); + if (msg == NULL) + { + fprintf(stderr, "ERROR: Failed to get symbol \"g_msg2\"\n"); + exit(EXIT_FAILURE); + } + + /* Execute testfunc2 */ + + testfunc(msg); + + /* Get symbols testfunc3 and msg3 */ + + testfunc = (CODE void (*)(FAR const char *))dlsym(handle, "testfunc3"); + if (testfunc == NULL) + { + fprintf(stderr, "ERROR: Failed to get symbol \"testfunc3\"\n"); + exit(EXIT_FAILURE); + } + + msg = (FAR const char *)dlsym(handle, "g_msg3"); + if (msg == NULL) + { + fprintf(stderr, "ERROR: Failed to get symbol \"g_msg3\"\n"); + exit(EXIT_FAILURE); + } + + /* Execute testfunc3 */ + + testfunc(msg); + + ret = dlclose(handle); + if (ret < 0) + { + fprintf(stderr, "ERROR: rmmod failed: %d\n", ret); + exit(EXIT_FAILURE); + } + + ret = umount(MOUNTPT); + if (ret < 0) + { + fprintf(stderr, "ERROR: umount(%s) failed: %d\n", + MOUNTPT, errno); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; +}