apps/examples/sotest: Extend test to check out module dependencies.

This commit is contained in:
Gregory Nutt 2017-01-27 15:11:44 -06:00
parent 32211e21b6
commit abd0362c64
7 changed files with 313 additions and 32 deletions

View File

@ -37,8 +37,13 @@
-include $(TOPDIR)/Make.defs
include $(APPDIR)/Make.defs
ALL_SUBDIRS = sotest
BUILD_SUBDIRS = sotest
ALL_SUBDIRS = sotest
BUILD_SUBDIRS = sotest
ifneq ($(CONFIG_MODULE_MAXDEPEND),0)
ALL_SUBDIRS += modprint
BUILD_SUBDIRS += modprint
endif
SOTEST_DIR = $(APPDIR)/examples/sotest
LIB_DIR = $(SOTEST_DIR)/lib

View File

@ -1,4 +1,5 @@
#!/bin/bash
# set -x
usage="Usage: $0 <test-dir-path>"
@ -22,12 +23,17 @@ 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`
tmplist=`find ${dir} -executable -type f | xargs nm | fgrep ' U ' | sed -e "s/^[ ]*//g" | cut -d' ' -f2 | sort | uniq`
# Remove the special symbol 'modprint'. It it is not exported by the
# base firmware, but rather in this test from one shared library to another.
varlist=`echo $tmplist | sed -e "s/modprint//g"`
# 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
# fail
echo "#include <nuttx/compiler.h>"
echo "#include <nuttx/binfmt/symtab.h>"

View File

@ -0,0 +1,2 @@
/modprint

View File

@ -0,0 +1,94 @@
############################################################################
# examples/sotest/lib/modprint/Makefile
#
# Copyright (C) 2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# 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 = modprint
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)

View File

@ -0,0 +1,115 @@
/****************************************************************************
* apps/examples/sotest/lib/modprint/modprint.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <sys/types.h>
#include <stdarg.h>
#include <dllfcn.h>
#include <syslog.h>
#include <nuttx/module.h>
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void modprint(FAR const char *fmt, ...);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct symtab_s g_exports[1] =
{
{
(FAR const char *)"modprint", (FAR const void *)modprint,
}
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: modprint
****************************************************************************/
static void modprint(FAR const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void)syslog(LOG_INFO, fmt, ap);
va_end(ap);
}
/****************************************************************************
* 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 = 1;
return OK;
}

View File

@ -40,18 +40,19 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdarg.h>
#include <dllfcn.h>
#include <syslog.h>
#include <nuttx/module.h>
/****************************************************************************
* Pre-processor Definitions
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Private data
****************************************************************************/
#if CONFIG_MODULE_MAXDEPEND > 0
void modprint(FAR const char *fmt, ...);
#endif
/****************************************************************************
* Private Function Prototypes
@ -96,14 +97,29 @@ static const struct symtab_s g_exports[6] =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: modprint
****************************************************************************/
#if CONFIG_MODULE_MAXDEPEND < 1
static void modprint(FAR const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void)syslog(LOG_INFO, fmt, ap);
va_end(ap);
}
#endif
/****************************************************************************
* Name: testfunc1
****************************************************************************/
static void testfunc1(FAR const char *msg)
{
syslog(LOG_INFO, "testfunc1: Hello, everyone!\n");
syslog(LOG_INFO, " caller: %s\n", msg);
modprint("testfunc1: Hello, everyone!\n");
modprint(" caller: %s\n", msg);
}
/****************************************************************************
@ -112,8 +128,8 @@ static void testfunc1(FAR const char *msg)
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);
modprint("testfunc2: Hope you are having a great day!\n");
modprint(" caller: %s\n", msg);
}
/****************************************************************************
@ -122,8 +138,8 @@ static void testfunc2(FAR const char *msg)
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);
modprint("testfunc3: Let's talk again very soon\n");
modprint(" caller: %s\n", msg);
}
/****************************************************************************
@ -132,7 +148,7 @@ static void testfunc3(FAR const char *msg)
static int module_uninitialize(FAR void *arg)
{
syslog(LOG_INFO, "module_uninitialize: arg=%p\n", arg);
modprint("module_uninitialize: arg=%p\n", arg);
return OK;
}
@ -150,7 +166,7 @@ static int module_uninitialize(FAR void *arg)
int module_initialize(FAR struct mod_info_s *modinfo)
{
syslog(LOG_INFO, "module_initialize:\n");
modprint("module_initialize:\n");
modinfo->uninitializer = module_uninitialize;
modinfo->arg = NULL;

View File

@ -1,7 +1,7 @@
/****************************************************************************
* examples/sotest/sotest_main.c
*
* Copyright (C) 2015, 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -111,7 +111,10 @@ int main(int argc, FAR char *argv[])
int sotest_main(int argc, char *argv[])
#endif
{
FAR void *handle;
#if CONFIG_MODULE_MAXDEPEND > 0
FAR void *handle1;
#endif
FAR void *handle2;
CODE void (*testfunc)(FAR const char *msg);
FAR const char *msg;
int ret;
@ -159,25 +162,41 @@ int sotest_main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
/* Install the test shared library */
#if CONFIG_MODULE_MAXDEPEND > 0
/* Install the first test shared library. The first shared library only
* verifies that symbols exported be one shared library can be used to
* resolve undefined symbols in a second shared library.
*/
handle = dlopen(MOUNTPT "/sotest", RTLD_NOW | RTLD_LOCAL);
if (handle == NULL)
/* Install the second test shared library */
handle1 = dlopen(MOUNTPT "/modprint", RTLD_NOW | RTLD_LOCAL);
if (handle1 == NULL)
{
fprintf(stderr, "ERROR: dlopen failed\n");
fprintf(stderr, "ERROR: dlopen(/modprint) failed\n");
exit(EXIT_FAILURE);
}
#endif
/* Install the second test shared library */
handle2 = dlopen(MOUNTPT "/sotest", RTLD_NOW | RTLD_LOCAL);
if (handle2 == NULL)
{
fprintf(stderr, "ERROR: dlopen(/sotest) failed\n");
exit(EXIT_FAILURE);
}
/* Get symbols testfunc1 and msg1 */
/* Get symbols testfunc1 and msg1 from the second test shared library */
testfunc = (CODE void (*)(FAR const char *))dlsym(handle, "testfunc1");
testfunc = (CODE void (*)(FAR const char *))dlsym(handle2, "testfunc1");
if (testfunc == NULL)
{
fprintf(stderr, "ERROR: Failed to get symbol \"testfunc1\"\n");
exit(EXIT_FAILURE);
}
msg = (FAR const char *)dlsym(handle, "g_msg1");
msg = (FAR const char *)dlsym(handle2, "g_msg1");
if (msg == NULL)
{
fprintf(stderr, "ERROR: Failed to get symbol \"g_msg1\"\n");
@ -190,14 +209,14 @@ int sotest_main(int argc, char *argv[])
/* Get symbols testfunc2 and msg2 */
testfunc = (CODE void (*)(FAR const char *))dlsym(handle, "testfunc2");
testfunc = (CODE void (*)(FAR const char *))dlsym(handle2, "testfunc2");
if (testfunc == NULL)
{
fprintf(stderr, "ERROR: Failed to get symbol \"testfunc2\"\n");
exit(EXIT_FAILURE);
}
msg = (FAR const char *)dlsym(handle, "g_msg2");
msg = (FAR const char *)dlsym(handle2, "g_msg2");
if (msg == NULL)
{
fprintf(stderr, "ERROR: Failed to get symbol \"g_msg2\"\n");
@ -210,14 +229,14 @@ int sotest_main(int argc, char *argv[])
/* Get symbols testfunc3 and msg3 */
testfunc = (CODE void (*)(FAR const char *))dlsym(handle, "testfunc3");
testfunc = (CODE void (*)(FAR const char *))dlsym(handle2, "testfunc3");
if (testfunc == NULL)
{
fprintf(stderr, "ERROR: Failed to get symbol \"testfunc3\"\n");
exit(EXIT_FAILURE);
}
msg = (FAR const char *)dlsym(handle, "g_msg3");
msg = (FAR const char *)dlsym(handle2, "g_msg3");
if (msg == NULL)
{
fprintf(stderr, "ERROR: Failed to get symbol \"g_msg3\"\n");
@ -228,12 +247,36 @@ int sotest_main(int argc, char *argv[])
testfunc(msg);
ret = dlclose(handle);
if (ret < 0)
#if CONFIG_MODULE_MAXDEPEND > 0
/* This should fail because the second shared library depends on the first. */
ret = dlclose(handle1);
if (ret == 0)
{
fprintf(stderr, "ERROR: rmmod failed: %d\n", ret);
fprintf(stderr, "ERROR: dlclose(handle1) succeeded with a dependency\n");
exit(EXIT_FAILURE);
}
#endif
/* Close the second shared library */
ret = dlclose(handle2);
if (ret < 0)
{
fprintf(stderr, "ERROR: rmmod(handle2) failed: %d\n", ret);
exit(EXIT_FAILURE);
}
#if CONFIG_MODULE_MAXDEPEND > 0
/* Now we should be able to close the first shared library. */
ret = dlclose(handle1);
if (ret < 0)
{
fprintf(stderr, "ERROR: rmmod(handle1) failed: %d\n", ret);
exit(EXIT_FAILURE);
}
#endif
ret = umount(MOUNTPT);
if (ret < 0)