summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-10-29 19:32:05 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-10-29 19:32:05 +0000
commit9e45144d3ad1420908cfdf84306c76f637829023 (patch)
tree63a4ac04f182a282aac2d649973c99285b12cad5
parentade5fb42679b7e890f29487ca850c65f9944fa1e (diff)
downloadnuttx-9e45144d3ad1420908cfdf84306c76f637829023.tar.gz
nuttx-9e45144d3ad1420908cfdf84306c76f637829023.tar.bz2
nuttx-9e45144d3ad1420908cfdf84306c76f637829023.zip
C++ constructors work with ELF load now
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5273 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--apps/examples/elf/elf_main.c80
-rw-r--r--apps/examples/elf/tests/helloxx/Makefile124
-rw-r--r--apps/examples/elf/tests/helloxx/hello++1.cpp60
-rw-r--r--apps/examples/elf/tests/helloxx/hello++2.cpp123
-rw-r--r--apps/examples/elf/tests/helloxx/hello++3.cpp132
-rw-r--r--apps/examples/elf/tests/helloxx/hello++4.cpp150
-rw-r--r--nuttx/arch/arm/src/arm/up_elf.c1
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_elf.c1
-rw-r--r--nuttx/binfmt/Kconfig7
-rw-r--r--nuttx/binfmt/binfmt_dumpmodule.c10
-rw-r--r--nuttx/binfmt/binfmt_execmodule.c60
-rw-r--r--nuttx/binfmt/binfmt_unloadmodule.c76
-rw-r--r--nuttx/binfmt/elf.c28
-rw-r--r--nuttx/binfmt/libelf/Kconfig7
-rw-r--r--nuttx/binfmt/libelf/Make.defs8
-rw-r--r--nuttx/binfmt/libelf/libelf.h54
-rw-r--r--nuttx/binfmt/libelf/libelf_ctors.c278
-rw-r--r--nuttx/binfmt/libelf/libelf_load.c58
-rw-r--r--nuttx/binfmt/libelf/libelf_sections.c284
-rw-r--r--nuttx/binfmt/libelf/libelf_uninit.c9
-rw-r--r--nuttx/binfmt/libelf/libelf_unload.c20
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_load.c18
-rw-r--r--nuttx/binfmt/nxflat.c12
-rw-r--r--nuttx/configs/stm32f4discovery/elf/Make.defs4
-rw-r--r--nuttx/configs/stm32f4discovery/elf/defconfig2
-rw-r--r--nuttx/configs/stm32f4discovery/scripts/gnu-elf.ld14
-rw-r--r--nuttx/include/nuttx/binfmt/binfmt.h25
-rw-r--r--nuttx/include/nuttx/binfmt/elf.h19
28 files changed, 1276 insertions, 388 deletions
diff --git a/apps/examples/elf/elf_main.c b/apps/examples/elf/elf_main.c
index 23a6b2d21..669de430d 100644
--- a/apps/examples/elf/elf_main.c
+++ b/apps/examples/elf/elf_main.c
@@ -41,6 +41,7 @@
#include <nuttx/compiler.h>
#include <sys/mount.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -129,6 +130,9 @@
* Private Data
****************************************************************************/
+static unsigned int g_mminitial; /* Initial memory usage */
+static unsigned int g_mmstep; /* Memory Usage at beginning of test step */
+
static const char delimiter[] =
"****************************************************************************";
@@ -146,6 +150,53 @@ extern const int nexports;
****************************************************************************/
/****************************************************************************
+ * Name: mm_update
+ ****************************************************************************/
+
+static void mm_update(FAR unsigned int *previous, FAR const char *msg)
+{
+ struct mallinfo mmcurrent;
+
+ /* Get the current memory usage */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mmcurrent = mallinfo();
+#else
+ (void)mallinfo(&mmcurrent);
+#endif
+
+ /* Show the change from the previous time */
+
+ printf("\nMemory Usage %s:\n", msg);
+ printf(" Before: %8u After: %8u Change: %8d\n",
+ *previous, mmcurrent.uordblks, (int)mmcurrent.uordblks - (int)*previous);
+
+ /* Set up for the next test */
+
+ *previous = mmcurrent.uordblks;
+}
+
+/****************************************************************************
+ * Name: mm_initmonitor
+ ****************************************************************************/
+
+static void mm_initmonitor(void)
+{
+ struct mallinfo mmcurrent;
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mmcurrent = mallinfo();
+#else
+ (void)mallinfo(&mmcurrent);
+#endif
+
+ g_mminitial = mmcurrent.uordblks;
+ g_mmstep = mmcurrent.uordblks;
+
+ printf("Initial memory usage: %d\n", mmcurrent.uordblks);
+}
+
+/****************************************************************************
* Name: testheader
****************************************************************************/
@@ -168,6 +219,10 @@ int elf_main(int argc, char *argv[])
int ret;
int i;
+ /* Initialize the memory monitor */
+
+ mm_initmonitor();
+
/* Initialize the ELF binary loader */
message("Initializing the ELF binary loader\n");
@@ -178,6 +233,8 @@ int elf_main(int argc, char *argv[])
exit(1);
}
+ mm_update(&g_mmstep, "after elf_initialize");
+
/* Create a ROM disk for the ROMFS filesystem */
message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR);
@@ -190,6 +247,8 @@ int elf_main(int argc, char *argv[])
exit(1);
}
+ mm_update(&g_mmstep, "after romdisk_register");
+
/* Mount the file system */
message("Mounting ROMFS filesystem at target=%s with source=%s\n",
@@ -203,7 +262,9 @@ int elf_main(int argc, char *argv[])
elf_uninitialize();
}
- /* Now excercise every progrm in the ROMFS file system */
+ mm_update(&g_mmstep, "after mount");
+
+ /* Now excercise every program in the ROMFS file system */
for (i = 0; dirlist[i]; i++)
{
@@ -223,17 +284,26 @@ int elf_main(int argc, char *argv[])
exit(1);
}
+ mm_update(&g_mmstep, "after load_module");
+
ret = exec_module(&bin, 50);
+
+ mm_update(&g_mmstep, "after exec_module");
+
if (ret < 0)
{
err("ERROR: Failed to execute program '%s'\n", dirlist[i]);
- unload_module(&bin);
+ }
+ else
+ {
+ message("Wait a bit for test completion\n");
+ sleep(4);
}
- message("Wait a bit for test completion\n");
- sleep(4);
+ unload_module(&bin);
+ mm_update(&g_mmstep, "after unload_module");
}
- message("End-of-Test.. Exiting\n");
+ mm_update(&g_mmstep, "End-of-Test");
return 0;
}
diff --git a/apps/examples/elf/tests/helloxx/Makefile b/apps/examples/elf/tests/helloxx/Makefile
new file mode 100644
index 000000000..d115fbeaf
--- /dev/null
+++ b/apps/examples/elf/tests/helloxx/Makefile
@@ -0,0 +1,124 @@
+############################################################################
+# examples/elf/tests/helloxx/Makefile
+#
+# Copyright (C) 2012 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)/.config
+-include $(TOPDIR)/Make.defs
+
+BIN1 = hello++1
+BIN2 = hello++2
+ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
+BIN3 = hello++3
+endif
+#BIN4 = hello++4
+ALL_BIN = $(BIN1) $(BIN2) $(BIN3) $(BIN4)
+
+SRCS1 = $(BIN1).c
+OBJS1 = $(SRCS1:.c=.o)
+
+SRCS2 = $(BIN2).c
+OBJS2 = $(SRCS2:.c=.o)
+
+ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
+SRCS3 = $(BIN3).c
+OBJS3 = $(SRCS3:.c=.o)
+endif
+
+#SRCS4 = $(BIN4).c
+#OBJS4 = $(SRCS4:.c=.o)
+
+SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4)
+OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4)
+
+LIBSTDC_STUBS_DIR = $(TOPDIR)/libxx
+LIBSTDC_STUBS_LIB = $(LIBSTDC_STUBS_DIR)/liblibxx.a
+
+all: $(BIN1) $(BIN2) $(BIN3) $(BIN4)
+
+$(OBJS): %.o: %.cpp
+ @echo "CC: $<"
+ @$(CXX) -c $(CXXELFFLAGS) $< -o $@
+
+# This contains libstdc++ stubs to that you can build C++ code
+# without actually having libstdc++
+
+$(LIBSTDC_STUBS_LIB):
+ @$(MAKE) -C $(LIBSTDC_STUBS_DIR) TOPDIR=$(TOPDIR)
+
+# BIN1 and BIN2 link just like C code because they contain no
+# static constructors. BIN1 is equivalent to a C hello world;
+# BIN2 contains a class that implements hello world, but it is
+# not statically initialized.
+
+$(BIN1): $(OBJS1)
+ @echo "LD: $<"
+ @$(LD) $(LDELFFLAGS) -o $@ $^
+
+$(BIN2): $(OBJS2)
+ @echo "LD: $<"
+ @$(LD) $(LDELFFLAGS) -o $@ $^
+
+# BIN3 is equivalent to BIN2 except that is uses static initializers
+
+ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
+$(BIN3): $(OBJS3)
+ @echo "LD: $<"
+ @$(LD) $(LDELFFLAGS) -o $@ $^
+endif
+
+# BIN4 is similar to BIN3 except that it uses the streams code from libstdc++
+#
+# NOTE: libstdc++ is not available for NuttX as of this writing
+#
+#$(BIN4): $(OBJS4)
+# @echo "LD: $<"
+# @$(LD) $(LDELFFLAGS) -o $@ $^
+
+clean:
+ @rm -f $(ALL_BIN) *.o *~ .*.swp core
+
+install: $(ALL_BIN)
+ @install -D $(BIN1) $(ROMFS_DIR)/$(BIN1)
+ @install -D $(BIN2) $(ROMFS_DIR)/$(BIN2)
+ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
+ @install -D $(BIN3) $(ROMFS_DIR)/$(BIN3)
+endif
+# @install -D $(BIN4) $(ROMFS_DIR)/$(BIN4)
+
+
+
+
+
+
+
diff --git a/apps/examples/elf/tests/helloxx/hello++1.cpp b/apps/examples/elf/tests/helloxx/hello++1.cpp
new file mode 100644
index 000000000..9ab9d4ded
--- /dev/null
+++ b/apps/examples/elf/tests/helloxx/hello++1.cpp
@@ -0,0 +1,60 @@
+/////////////////////////////////////////////////////////////////////////////
+// examples/elf/tests/helloxx/hello++1.c
+//
+// Copyright (C) 2012 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.
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// This is an trivial version of "Hello, World" program. It illustrates
+// that we can build C programs using the C++ compiler.
+//
+// - Building a C++ program to use the C library
+// - No class creation
+// - NO Streams
+// - NO Static constructor and destructors
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Included Files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+
+/////////////////////////////////////////////////////////////////////////////
+// Public Functions
+/////////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char **argv)
+{
+ printf("Hello, World!\n");
+ return 0;
+}
diff --git a/apps/examples/elf/tests/helloxx/hello++2.cpp b/apps/examples/elf/tests/helloxx/hello++2.cpp
new file mode 100644
index 000000000..f1268dda5
--- /dev/null
+++ b/apps/examples/elf/tests/helloxx/hello++2.cpp
@@ -0,0 +1,123 @@
+/////////////////////////////////////////////////////////////////////////////
+// examples/elf/tests/helloxx/hello++2.c
+//
+// Copyright (C) 2012 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.
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// This is an another trivial version of "Hello, World" design. It illustrates
+//
+// - Building a C++ program to use the C library
+// - Basic class creation
+// - NO Streams
+// - NO Static constructor and destructors
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Included Files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+
+/////////////////////////////////////////////////////////////////////////////
+// Classes
+/////////////////////////////////////////////////////////////////////////////
+
+class CThingSayer
+{
+ const char *szWhatToSay;
+public:
+ CThingSayer(void)
+ {
+ printf("CThingSayer::CThingSayer: I am!\n");
+ szWhatToSay = (const char*)NULL;
+ }
+
+ ~CThingSayer(void)
+ {
+ printf("CThingSayer::~CThingSayer: I cease to be\n");
+ if (szWhatToSay)
+ {
+ printf("CThingSayer::~CThingSayer: I will never say '%s' again\n",
+ szWhatToSay);
+ }
+ szWhatToSay = (const char*)NULL;
+ }
+
+ void Initialize(const char *czSayThis)
+ {
+ printf("CThingSayer::Initialize: When told, I will say '%s'\n",
+ czSayThis);
+ szWhatToSay = czSayThis;
+ }
+
+ void SayThing(void)
+ {
+ printf("CThingSayer::SayThing: I am now saying '%s'\n", szWhatToSay);
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Public Functions
+/////////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char **argv)
+{
+ CThingSayer *MyThingSayer;
+
+ printf("main: Started. Creating MyThingSayer\n");
+
+ // Create an instance of the CThingSayer class
+ // We should see the message from constructor, CThingSayer::CThingSayer(),
+
+ MyThingSayer = new CThingSayer;
+ printf("main: Created MyThingSayer=0x%08lx\n", (long)MyThingSayer);
+
+ // Tell MyThingSayer that "Hello, World!" is the string to be said
+
+ printf("main: Calling MyThingSayer->Initialize\n");;
+ MyThingSayer->Initialize("Hello, World!");
+
+ // Tell MyThingSayer to say the thing we told it to say
+
+ printf("main: Calling MyThingSayer->SayThing\n");;
+ MyThingSayer->SayThing();
+
+ // We should see the message from the destructor,
+ // CThingSayer::~CThingSayer(), AFTER we see the following
+
+ printf("main: Destroying MyThingSayer\n");
+ delete MyThingSayer;
+
+ printf("main: Returning\n");;
+ return 0;
+}
diff --git a/apps/examples/elf/tests/helloxx/hello++3.cpp b/apps/examples/elf/tests/helloxx/hello++3.cpp
new file mode 100644
index 000000000..6661a3fd1
--- /dev/null
+++ b/apps/examples/elf/tests/helloxx/hello++3.cpp
@@ -0,0 +1,132 @@
+/////////////////////////////////////////////////////////////////////////////
+// examples/elf/tests/helloxx/hello++3.c
+//
+// Copyright (C) 2012 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.
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// This is an another trivial version of "Hello, World" design. It illustrates
+//
+// - Building a C++ program to use the C library and stdio
+// - Basic class creation with virtual methods.
+// - Static constructor and destructors (in main program only)
+// - NO Streams
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Included Files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+
+/////////////////////////////////////////////////////////////////////////////
+// Classes
+/////////////////////////////////////////////////////////////////////////////
+
+class CThingSayer
+{
+ const char *szWhatToSay;
+public:
+ CThingSayer(void);
+ virtual ~CThingSayer(void);
+ virtual void Initialize(const char *czSayThis);
+ virtual void SayThing(void);
+};
+
+// A static instance of the CThingSayer class. This instance MUST
+// be constructed by the system BEFORE the program is started at
+// main() and must be destructed by the system AFTER the main()
+// returns to the system
+
+static CThingSayer MyThingSayer;
+
+// These are implementations of the methods of the CThingSayer class
+
+CThingSayer::CThingSayer(void)
+{
+ printf("CThingSayer::CThingSayer: I am!\n");
+ szWhatToSay = (const char*)NULL;
+}
+
+CThingSayer::~CThingSayer(void)
+{
+ printf("CThingSayer::~CThingSayer: I cease to be\n");
+ if (szWhatToSay)
+ {
+ printf("CThingSayer::~CThingSayer: I will never say '%s' again\n",
+ szWhatToSay);
+ }
+ szWhatToSay = (const char*)NULL;
+}
+
+void CThingSayer::Initialize(const char *czSayThis)
+{
+ printf("CThingSayer::Initialize: When told, I will say '%s'\n",
+ czSayThis);
+ szWhatToSay = czSayThis;
+}
+
+void CThingSayer::SayThing(void)
+{
+ printf("CThingSayer::SayThing: I am now saying '%s'\n", szWhatToSay);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Public Functions
+/////////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char **argv)
+{
+ // We should see the message from constructor, CThingSayer::CThingSayer(),
+ // BEFORE we see the following messages. That is proof that the
+ // C++ static initializer is working
+
+ printf("main: Started. MyThingSayer should already exist\n");
+
+ // Tell MyThingSayer that "Hello, World!" is the string to be said
+
+ printf("main: Calling MyThingSayer.Initialize\n");;
+ MyThingSayer.Initialize("Hello, World!");
+
+ // Tell MyThingSayer to say the thing we told it to say
+
+ printf("main: Calling MyThingSayer.SayThing\n");;
+ MyThingSayer.SayThing();
+
+ // We are finished, return. We should see the message from the
+ // destructor, CThingSayer::~CThingSayer(), AFTER we see the following
+ // message. That is proof that the C++ static destructor logic
+ // is working
+
+ printf("main: Returning. MyThingSayer should be destroyed\n");;
+ return 0;
+}
diff --git a/apps/examples/elf/tests/helloxx/hello++4.cpp b/apps/examples/elf/tests/helloxx/hello++4.cpp
new file mode 100644
index 000000000..7db2564ed
--- /dev/null
+++ b/apps/examples/elf/tests/helloxx/hello++4.cpp
@@ -0,0 +1,150 @@
+/////////////////////////////////////////////////////////////////////////////
+// examples/elf/tests/helloxx/hello++4.c
+//
+// Copyright (C) 2012 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.
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// This is an excessively complex version of "Hello, World" design to
+// illustrate some basic properties of C++:
+//
+// - Building a C++ program
+// - Streams / statically linked libstdc++
+// - Static constructor and destructors (in main program only)
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
+// Included Files
+/////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+#include <iostream>
+
+#ifndef NULL
+# define NULL ((void*)0L)
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// Classes
+/////////////////////////////////////////////////////////////////////////////
+
+using namespace std;
+
+// A hello world sayer class
+
+class CThingSayer
+{
+ const char *szWhatToSay;
+public:
+ CThingSayer(void);
+ virtual ~CThingSayer(void);
+ virtual void Initialize(const char *czSayThis);
+ virtual void SayThing(void);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Private Data
+/////////////////////////////////////////////////////////////////////////////
+
+// A static instance of the CThingSayer class. This instance MUST
+// be constructed by the system BEFORE the program is started at
+// main() and must be destructed by the system AFTER the main()
+// returns to the system
+
+static CThingSayer MyThingSayer;
+
+/////////////////////////////////////////////////////////////////////////////
+// Method Implementations
+/////////////////////////////////////////////////////////////////////////////
+
+// These are implementations of the methods of the CThingSayer class
+
+CThingSayer::CThingSayer(void)
+{
+ cout << "CThingSayer::CThingSayer: I am!" << endl;
+ szWhatToSay = (const char*)NULL;
+}
+
+CThingSayer::~CThingSayer(void)
+{
+ cout << "CThingSayer::~CThingSayer: I cease to be" << endl;
+ if (szWhatToSay)
+ {
+ cout << "CThingSayer::~CThingSayer: I will never say '"
+ << szWhatToSay << "' again" << endl;
+ }
+ szWhatToSay = (const char*)NULL;
+}
+
+void CThingSayer::Initialize(const char *czSayThis)
+{
+ cout << "CThingSayer::Initialize: When told, I will say '"
+ << czSayThis << "'" << endl;
+ szWhatToSay = czSayThis;
+}
+
+void CThingSayer::SayThing(void)
+{
+ cout << "CThingSayer::SayThing: I am now saying '"
+ << szWhatToSay << "'" << endl;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Public Functions
+/////////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char **argv)
+{
+ // We should see the message from constructor, CThingSayer::CThingSayer(),
+ // BEFORE we see the following messages. That is proof that the
+ // C++ static initializer is working
+
+ cout << "main: Started" << endl;
+
+ // Tell MyThingSayer that "Hello, World!" is the string to be said
+
+ cout << "main: Calling MyThingSayer.Initialize" << endl;
+ MyThingSayer.Initialize("Hello, World!");
+
+ // Tell MyThingSayer to say the thing we told it to say
+
+ cout << "main: Calling MyThingSayer.SayThing" << endl;
+ MyThingSayer.SayThing();
+
+ // We are finished, return. We should see the message from the
+ // destructor, CThingSayer::~CThingSayer(), AFTER we see the following
+ // message. That is proof that the C++ static destructor logic
+ // is working
+
+ cout << "main: Returning" << endl;
+ return 0;
+}
diff --git a/nuttx/arch/arm/src/arm/up_elf.c b/nuttx/arch/arm/src/arm/up_elf.c
index b78da02c1..2dd8366aa 100644
--- a/nuttx/arch/arm/src/arm/up_elf.c
+++ b/nuttx/arch/arm/src/arm/up_elf.c
@@ -184,6 +184,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
break;
case R_ARM_ABS32:
+ case R_ARM_TARGET1: /* New ABI: TARGET1 always treated as ABS32 */
{
bvdbg("Performing ABS32 link at addr=%08lx [%08lx] to sym=%p st_value=%08lx\n",
(long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value);
diff --git a/nuttx/arch/arm/src/armv7-m/up_elf.c b/nuttx/arch/arm/src/armv7-m/up_elf.c
index 1cc1fa32a..b838a6905 100644
--- a/nuttx/arch/arm/src/armv7-m/up_elf.c
+++ b/nuttx/arch/arm/src/armv7-m/up_elf.c
@@ -178,6 +178,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
break;
case R_ARM_ABS32:
+ case R_ARM_TARGET1: /* New ABI: TARGET1 always treated as ABS32 */
{
bvdbg("Performing ABS32 link at addr=%08lx [%08lx] to sym=%p st_value=%08lx\n",
(long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value);
diff --git a/nuttx/binfmt/Kconfig b/nuttx/binfmt/Kconfig
index 4d020163e..ae02c276a 100644
--- a/nuttx/binfmt/Kconfig
+++ b/nuttx/binfmt/Kconfig
@@ -34,6 +34,13 @@ endif
endif
+config BINFMT_CONSTRUCTORS
+ bool "C++ Static Constructor Support"
+ default n
+ depends on HAVE_CXX && ELF # FIX ME: Currently only supported for ELF
+ ---help---
+ Build in support for C++ constructors in loaded modules.
+
config SYMTAB_ORDEREDBYNAME
bool "Symbol Tables Ordered by Name"
default n
diff --git a/nuttx/binfmt/binfmt_dumpmodule.c b/nuttx/binfmt/binfmt_dumpmodule.c
index 06e97e457..e095c4a67 100644
--- a/nuttx/binfmt/binfmt_dumpmodule.c
+++ b/nuttx/binfmt/binfmt_dumpmodule.c
@@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_dumpmodule.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
@@ -90,8 +90,12 @@ int dump_module(FAR const struct binary_s *bin)
bdbg(" filename: %s\n", bin->filename);
bdbg(" argv: %p\n", bin->argv);
bdbg(" entrypt: %p\n", bin->entrypt);
- bdbg(" ispace: %p size=%d\n", bin->ispace, bin->isize);
- bdbg(" dspace: %p\n", bin->dspace);
+ bdbg(" mapped: %p size=%d\n", bin->mapped, bin->mapsize);
+ bdbg(" alloc: %p %p\n", bin->alloc[0], bin->alloc[1]);
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ bdbg(" ctors: %p nctors=%d\n", bin->ctors, bin->nctors);
+ bdbg(" dtors: %p ndtors=%d\n", bin->dtors, bin->ndtors);
+#endif
bdbg(" stacksize: %d\n", bin->stacksize);
}
return OK;
diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c
index bc76d4acf..b00248183 100644
--- a/nuttx/binfmt/binfmt_execmodule.c
+++ b/nuttx/binfmt/binfmt_execmodule.c
@@ -71,6 +71,39 @@
****************************************************************************/
/****************************************************************************
+ * Name: exec_ctors
+ *
+ * Description:
+ * Execute C++ static constructors.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+static inline void exec_ctors(FAR const struct binary_s *binp)
+{
+ elf_ctor_t *ctor = binp->ctors;
+ int i;
+
+ /* Execute each constructor */
+
+ for (i = 0; i < binp->nctors; i++)
+ {
+ bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor);
+
+ (*ctor)();
+ ctor++;
+ }
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -87,7 +120,7 @@
*
****************************************************************************/
-int exec_module(FAR const struct binary_s *bin, int priority)
+int exec_module(FAR const struct binary_s *binp, int priority)
{
FAR _TCB *tcb;
#ifndef CONFIG_CUSTOM_STACK
@@ -100,14 +133,14 @@ int exec_module(FAR const struct binary_s *bin, int priority)
/* Sanity checking */
#ifdef CONFIG_DEBUG
- if (!bin || !bin->ispace || !bin->entrypt || bin->stacksize <= 0)
+ if (!binp || !binp->entrypt || binp->stacksize <= 0)
{
err = EINVAL;
goto errout;
}
#endif
- bdbg("Executing %s\n", bin->filename);
+ bdbg("Executing %s\n", binp->filename);
/* Allocate a TCB for the new task. */
@@ -121,7 +154,7 @@ int exec_module(FAR const struct binary_s *bin, int priority)
/* Allocate the stack for the new task */
#ifndef CONFIG_CUSTOM_STACK
- stack = (FAR uint32_t*)malloc(bin->stacksize);
+ stack = (FAR uint32_t*)malloc(binp->stacksize);
if (!tcb)
{
err = ENOMEM;
@@ -130,11 +163,13 @@ int exec_module(FAR const struct binary_s *bin, int priority)
/* Initialize the task */
- ret = task_init(tcb, bin->filename, priority, stack, bin->stacksize, bin->entrypt, bin->argv);
+ ret = task_init(tcb, binp->filename, priority, stack,
+ binp->stacksize, binp->entrypt, binp->argv);
#else
/* Initialize the task */
- ret = task_init(tcb, bin->filename, priority, stack, bin->entrypt, bin->argv);
+ ret = task_init(tcb, binp->filename, priority, stack,
+ binp->entrypt, binp->argv);
#endif
if (ret < 0)
{
@@ -143,10 +178,12 @@ int exec_module(FAR const struct binary_s *bin, int priority)
goto errout_with_stack;
}
- /* Add the DSpace address as the PIC base address */
+ /* Add the D-Space address as the PIC base address. By convention, this
+ * must be the first allocated address space.
+ */
#ifdef CONFIG_PIC
- tcb->dspace = bin->dspace;
+ tcb->dspace = binp->alloc[0];
/* Re-initialize the task's initial state to account for the new PIC base */
@@ -157,6 +194,12 @@ int exec_module(FAR const struct binary_s *bin, int priority)
pid = tcb->pid;
+ /* Execute all of the C++ static constructors */
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ exec_ctors(binp);
+#endif
+
/* Then activate the task at the provided priority */
ret = task_activate(tcb);
@@ -166,6 +209,7 @@ int exec_module(FAR const struct binary_s *bin, int priority)
bdbg("task_activate() failed: %d\n", err);
goto errout_with_stack;
}
+
return (int)pid;
errout_with_stack:
diff --git a/nuttx/binfmt/binfmt_unloadmodule.c b/nuttx/binfmt/binfmt_unloadmodule.c
index 0de9dfccd..15b238357 100644
--- a/nuttx/binfmt/binfmt_unloadmodule.c
+++ b/nuttx/binfmt/binfmt_unloadmodule.c
@@ -1,7 +1,7 @@
/****************************************************************************
* binfmt/binfmt_loadmodule.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
@@ -68,6 +68,39 @@
****************************************************************************/
/****************************************************************************
+ * Name: exec_dtors
+ *
+ * Description:
+ * Execute C++ static constructors.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+static inline void exec_dtors(FAR const struct binary_s *binp)
+{
+ elf_dtor_t *dtor = binp->dtors;
+ int i;
+
+ /* Execute each destructor */
+
+ for (i = 0; i < binp->ndtors; i++)
+ {
+ bvdbg("Calling dtor %d at %p\n", i, (FAR void *)dtor);
+
+ (*dtor)();
+ dtor++;
+ }
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -76,7 +109,12 @@
*
* Description:
* Unload a (non-executing) module from memory. If the module has
- * been started (via exec_module), calling this will be fatal.
+ * been started (via exec_module) and has not exited, calling this will
+ * be fatal.
+ *
+ * However, this function must be called after the module exist. How
+ * this is done is up to your logic. Perhaps you register it to be
+ * called by on_exit()?
*
* Returned Value:
* This is a NuttX internal function so it follows the convention that
@@ -85,22 +123,40 @@
*
****************************************************************************/
-int unload_module(FAR const struct binary_s *bin)
+int unload_module(FAR const struct binary_s *binp)
{
- if (bin)
+ int i;
+
+ if (binp)
{
- if (bin->ispace)
+
+ /* Execute C++ desctructors */
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ exec_dtors(binp);
+#endif
+
+ /* Unmap mapped address spaces */
+
+ if (binp->mapped)
{
- bvdbg("Unmapping ISpace: %p\n", bin->ispace);
- munmap(bin->ispace, bin->isize);
+ bvdbg("Unmapping address space: %p\n", binp->mapped);
+
+ munmap(binp->mapped, binp->mapsize);
}
- if (bin->dspace)
+ /* Free allocated address spaces */
+
+ for (i = 0; i < BINFMT_NALLOC; i++)
{
- bvdbg("Freeing DSpace: %p\n", bin->dspace);
- free(bin->dspace);
+ if (binp->alloc[i])
+ {
+ bvdbg("Freeing alloc[%d]: %p\n", i, binp->alloc[i]);
+ free(binp->alloc[i]);
+ }
}
}
+
return OK;
}
diff --git a/nuttx/binfmt/elf.c b/nuttx/binfmt/elf.c
index 57123ed95..26057ffc1 100644
--- a/nuttx/binfmt/elf.c
+++ b/nuttx/binfmt/elf.c
@@ -114,7 +114,7 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
bdbg(" alloc: %08lx\n", (long)loadinfo->alloc);
bdbg(" allocsize: %ld\n", (long)loadinfo->allocsize);
bdbg(" filelen: %ld\n", (long)loadinfo->filelen);
-#ifdef CONFIG_ELF_CONSTRUCTORS
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
bdbg(" ctors: %08lx\n", (long)loadinfo->ctors);
bdbg(" nctors: %d\n", loadinfo->nctors);
#endif
@@ -211,13 +211,31 @@ static int elf_loadbinary(struct binary_s *binp)
/* Return the load information */
binp->entrypt = (main_t)(loadinfo.alloc + loadinfo.ehdr.e_entry);
- binp->ispace = (void*)loadinfo.alloc;
- binp->dspace = NULL;
- binp->isize = loadinfo.allocsize;
+ binp->alloc[0] = (FAR void *)loadinfo.alloc;
binp->stacksize = CONFIG_ELF_STACKSIZE;
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ /* Save information about constructors. NOTE: desctructors are not
+ * yet supported.
+ */
+
+ binp->ctors = loadinfo.ctors;
+ binp->nctors = loadinfo.nctors;
+
+ /* Was memory allocated for constructors? */
+
+ if (!loadinfo.newabi)
+ {
+ /* Yes.. save the allocation address so that it can be freed by
+ * unload module.
+ */
+
+ binp->alloc[1] = (FAR void *)loadinfo.ctors;
+ }
+#endif
+
elf_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt,
- MIN(binp->isize - loadinfo.ehdr.e_entry, 512));
+ MIN(loadinfo.allocsize - loadinfo.ehdr.e_entry, 512));
elf_uninit(&loadinfo);
return OK;
diff --git a/nuttx/binfmt/libelf/Kconfig b/nuttx/binfmt/libelf/Kconfig
index 5dc4a2d9f..f6f579276 100644
--- a/nuttx/binfmt/libelf/Kconfig
+++ b/nuttx/binfmt/libelf/Kconfig
@@ -32,13 +32,6 @@ config ELF_BUFFERINCR
will need to be read (such as symbol names). This value specifies the size
increment to use each time the buffer is reallocated. Default: 32
-config ELF_CONSTRUCTORS
- bool "C++ Static Constructor Support"
- default n
- depends on HAVE_CXX
- ---help---
- Build in support for C++ constructors in ELF modules.
-
config ELF_DUMPBUFFER
bool "Dump ELF buffers"
default n
diff --git a/nuttx/binfmt/libelf/Make.defs b/nuttx/binfmt/libelf/Make.defs
index cf2507a99..26198ade2 100644
--- a/nuttx/binfmt/libelf/Make.defs
+++ b/nuttx/binfmt/libelf/Make.defs
@@ -41,11 +41,11 @@ BINFMT_CSRCS += elf.c
# ELF library
-BINFMT_CSRCS += libelf_init.c libelf_uninit.c libelf_load.c \
- libelf_unload.c libelf_verify.c libelf_read.c \
- libelf_bind.c libelf_symbols.c libelf_iobuffer.c
+BINFMT_CSRCS += libelf_bind.c libelf_init.c libelf_iobuffer.c libelf_load.c \
+ libelf_read.c libelf_sections.c libelf_symbols.c libelf_uninit.c \
+ libelf_unload.c libelf_verify.c
-ifeq ($(CONFIG_ELF_CONSTRUCTORS),y)
+ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
BINFMT_CSRCS += libelf_ctors.c
endif
diff --git a/nuttx/binfmt/libelf/libelf.h b/nuttx/binfmt/libelf/libelf.h
index 0d13515cc..bea92496a 100644
--- a/nuttx/binfmt/libelf/libelf.h
+++ b/nuttx/binfmt/libelf/libelf.h
@@ -86,6 +86,39 @@ int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset);
/****************************************************************************
+ * Name: elf_loadshdrs
+ *
+ * Description:
+ * Loads section headers into memory.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo);
+
+/****************************************************************************
+ * Name: elf_findsection
+ *
+ * Description:
+ * A section by its name.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ * sectname - Name of the section to find
+ *
+ * Returned Value:
+ * On success, the index to the section is returned; A negated errno value
+ * is returned on failure.
+ *
+ ****************************************************************************/
+
+int elf_findsection(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const char *sectname);
+
+/****************************************************************************
* Name: elf_findsymtab
*
* Description:
@@ -199,27 +232,8 @@ int elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment);
*
****************************************************************************/
-#ifdef CONFIG_ELF_CONSTRUCTORS
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo);
#endif
-/****************************************************************************
- * Name: elf_doctors
- *
- * Description:
- * Execute C++ static constructors.
- *
- * Input Parameters:
- * loadinfo - Load state information
- *
- * Returned Value:
- * 0 (OK) is returned on success and a negated errno is returned on
- * failure.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ELF_CONSTRUCTORS
-int elf_doctors(FAR struct elf_loadinfo_s *loadinfo);
-#endif
-
#endif /* __BINFMT_LIBELF_LIBELF_H */
diff --git a/nuttx/binfmt/libelf/libelf_ctors.c b/nuttx/binfmt/libelf/libelf_ctors.c
index c53923d44..a57fc37d9 100644
--- a/nuttx/binfmt/libelf/libelf_ctors.c
+++ b/nuttx/binfmt/libelf/libelf_ctors.c
@@ -49,7 +49,7 @@
#include "libelf.h"
-#ifdef CONFIG_ELF_CONSTRUCTORS
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
/****************************************************************************
* Pre-Processor Definitions
@@ -68,166 +68,6 @@
****************************************************************************/
/****************************************************************************
- * Name: elf_sectname
- *
- * Description:
- * Get the symbol name in loadinfo->iobuffer[].
- *
- * Returned Value:
- * 0 (OK) is returned on success and a negated errno is returned on
- * failure.
- *
- ****************************************************************************/
-
-static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
- FAR const Elf32_Shdr *shdr)
-{
- FAR Elf32_Shdr *shstr;
- FAR uint8_t *buffer;
- off_t offset;
- size_t readlen;
- size_t bytesread;
- int shstrndx;
- int ret;
-
- /* Get the section header table index of the entry associated with the
- * section name string table. If the file has no section name string table,
- * this member holds the value SH_UNDEF.
- */
-
- shstrndx = loadinfo->ehdr.e_shstrndx;
- if (shstrndx == SHN_UNDEF)
- {
- bdbg("No section header string table\n");
- return -EINVAL;
- }
-
- /* Get the section name string table section header */
-
- shstr = &loadinfo->shdr[shstrndx];
-
- /* Get the file offset to the string that is the name of the section. This
- * is the sum of:
- *
- * shstr->sh_offset: The file offset to the first byte of the section
- * header string table data.
- * shdr->sh_name: The offset to the name of the section in the section
- * name table
- */
-
- offset = shstr->sh_offset + shdr->sh_name;
-
- /* Loop until we get the entire section name into memory */
-
- buffer = loadinfo->iobuffer;
- bytesread = 0;
-
- for (;;)
- {
- /* Get the number of bytes to read */
-
- readlen = loadinfo->buflen - bytesread;
- if (offset + readlen > loadinfo->filelen)
- {
- readlen = loadinfo->filelen - offset;
- if (readlen <= 0)
- {
- bdbg("At end of file\n");
- return -EINVAL;
- }
- }
-
- /* Read that number of bytes into the array */
-
- buffer = &loadinfo->iobuffer[bytesread];
- ret = elf_read(loadinfo, buffer, readlen, offset);
- if (ret < 0)
- {
- bdbg("Failed to read section name\n");
- return ret;
- }
-
- bytesread += readlen;
-
- /* Did we read the NUL terminator? */
-
- if (memchr(buffer, '\0', readlen) != NULL)
- {
- /* Yes, the buffer contains a NUL terminator. */
-
- return OK;
- }
-
- /* No.. then we have to read more */
-
- ret = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
- if (ret < 0)
- {
- bdbg("elf_reallocbuffer failed: %d\n", ret);
- return ret;
- }
- }
-
- /* We will not get here */
-
- return OK;
-}
-
-/****************************************************************************
- * Name: elf_findctors
- *
- * Description:
- * Find C++ static constructors.
- *
- * Input Parameters:
- * loadinfo - Load state information
- *
- * Returned Value:
- * On success, the index to the CTOR section is returned; A negated errno
- * value is returned on failure.
- *
- ****************************************************************************/
-
-static inline int elf_findctors(FAR struct elf_loadinfo_s *loadinfo)
-{
- FAR const Elf32_Shdr *shdr;
- int ret;
- int i;
-
- /* Search through the shdr[] array in loadinfo for a section named .ctors */
-
- for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
- {
- /* Get the name of this section */
-
- shdr = &loadinfo->shdr[i];
- ret = elf_sectname(loadinfo, shdr);
- if (ret < 0)
- {
- bdbg("elf_sectname failed: %d\n", ret);
- return ret;
- }
-
- /* Check if the name of this section if ".ctors" */
-
- bvdbg("%d. Comparing \"%s\" and .ctors\"\n", i, loadinfo->iobuffer);
-
- if (strcmp(".ctors", (FAR const char *)loadinfo->iobuffer) == 0)
- {
- /* We found it... return the index */
-
- return i;
- }
- }
-
- /* We failed to find the .ctors sections. This may not be an error; maybe
- * there are no static constructors.
- */
-
- return -ENOENT;
-}
-
-/****************************************************************************
* Public Functions
****************************************************************************/
@@ -267,16 +107,21 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
return -ENOMEM;
}
- /* Find the index to the section named ".ctors" */
+ /* Find the index to the section named ".ctors." NOTE: On old ABI system,
+ * .ctors is the name of the section containing the list of constructors;
+ * On newer systems, the similar section is called .init_array. It is
+ * expected that the linker script will force the sectino name to be ".ctors"
+ * in either case.
+ */
- ctoridx = elf_findctors(loadinfo);
+ ctoridx = elf_findsection(loadinfo, ".ctors");
if (ctoridx < 0)
{
/* This may not be a failure. -ENOENT indicates that the file has no
* static constructor section.
*/
- bvdbg("elf_findctors failed: %d\n", ctoridx);
+ bvdbg("elf_findsection .ctors section failed: %d\n", ctoridx);
return ret == -ENOENT ? OK : ret;
}
@@ -286,7 +131,9 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
shdr = &loadinfo->shdr[ctoridx];
- /* Allocate memory to hold a copy of the .ctor section */
+ /* Get the size of the .ctor section and the number of constructors that
+ * will need to be called.
+ */
ctorsize = shdr->sh_size;
loadinfo->nctors = ctorsize / sizeof(elf_ctor_t);
@@ -302,71 +149,72 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
{
/* Check an assumption that we made above */
- DEBUGASSERT(shdr->sh_entsize == sizeof(elf_ctor_t));
-
- loadinfo->ctors = (elf_ctor_t)kmalloc(ctorsize);
- if (!loadinfo->ctors)
- {
- bdbg("Failed to allocate memory for .ctors\n");
- return -ENOMEM;
- }
+ DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(elf_ctor_t));
- /* Read the section header table into memory */
+ /* In the old ABI, the .ctors section is not allocated. In that case,
+ * we need to allocate memory to hold the .ctors and then copy the
+ * from the file into the allocated memory.
+ *
+ * SHF_ALLOC indicates that the section requires memory during
+ * execution.
+ */
- ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize,
- shdr->sh_offset);
- if (ret < 0)
+ if ((shdr->sh_flags & SHF_ALLOC) == 0)
{
- bdbg("Failed to allocate .ctors: %d\n", ret);
- }
+ /* Not loaded -> Old ABI. */
- /* Fix up all of the .ctor addresses */
+ loadinfo->newabi = false;
- for (i = 0; i < loadinfo->nctors; i++)
- {
- FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]);
+ /* Allocate memory to hold a copy of the .ctor section */
- bvdbg("ctor %d: %08lx + %08lx = %08lx\n", i,
- *ptr, loadinfo->alloc, *ptr + loadinfo->alloc);
+ loadinfo->ctors = (elf_ctor_t*)kmalloc(ctorsize);
+ if (!loadinfo->ctors)
+ {
+ bdbg("Failed to allocate memory for .ctors\n");
+ return -ENOMEM;
+ }
- *ptr += loadinfo->alloc;
- }
- }
+ /* Read the section header table into memory */
- return OK;
-}
+ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize,
+ shdr->sh_offset);
+ if (ret < 0)
+ {
+ bdbg("Failed to allocate .ctors: %d\n", ret);
+ return ret;
+ }
-/****************************************************************************
- * Name: elf_doctors
- *
- * Description:
- * Execute C++ static constructors.
- *
- * Input Parameters:
- * loadinfo - Load state information
- *
- * Returned Value:
- * 0 (OK) is returned on success and a negated errno is returned on
- * failure.
- *
- ****************************************************************************/
+ /* Fix up all of the .ctor addresses. Since the addresses
+ * do not lie in allocated memory, there will be no relocation
+ * section for them.
+ */
-int elf_doctors(FAR struct elf_loadinfo_s *loadinfo)
-{
- elf_ctor_t ctor = (elf_ctor_t)loadinfo->ctors;
- int i;
+ for (i = 0; i < loadinfo->nctors; i++)
+ {
+ FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]);
- /* Execute each constructor */
+ bvdbg("ctor %d: %08lx + %08lx = %08lx\n",
+ i, *ptr, loadinfo->alloc, *ptr + loadinfo->alloc);
- for (i = 0; i < loadinfo->nctors; i++)
- {
- bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor);
+ *ptr += loadinfo->alloc;
+ }
+ }
+ else
+ {
+ /* Loaded -> New ABI. */
- ctor();
- ctor++;
+ loadinfo->newabi = true;
+
+ /* Save the address of the .ctors (actually, .init_array) where it was
+ * loaded into memory. Since the .ctors lie in allocated memory, they
+ * will be relocated via the normal mechanism.
+ */
+
+ loadinfo->ctors = (elf_ctor_t*)shdr->sh_addr;
+ }
}
return OK;
}
-#endif /* CONFIG_ELF_CONSTRUCTORS */
+#endif /* CONFIG_BINFMT_CONSTRUCTORS */
diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c
index 505e2c813..221ae8d43 100644
--- a/nuttx/binfmt/libelf/libelf_load.c
+++ b/nuttx/binfmt/libelf/libelf_load.c
@@ -76,62 +76,6 @@
****************************************************************************/
/****************************************************************************
- * Name: elf_loadshdrs
- *
- * Description:
- * Loads section headers into memory.
- *
- * Returned Value:
- * 0 (OK) is returned on success and a negated errno is returned on
- * failure.
- *
- ****************************************************************************/
-
-static inline int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
-{
- size_t shdrsize;
- int ret;
-
- DEBUGASSERT(loadinfo->shdr == NULL);
-
- /* Verify that there are sections */
-
- if (loadinfo->ehdr.e_shnum < 1)
- {
- bdbg("No sections(?)\n");
- return -EINVAL;
- }
-
- /* Get the total size of the section header table */
-
- shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->ehdr.e_shnum;
- if(loadinfo->ehdr.e_shoff + shdrsize > loadinfo->filelen)
- {
- bdbg("Insufficent space in file for section header table\n");
- return -ESPIPE;
- }
-
- /* Allocate memory to hold a working copy of the sector header table */
-
- loadinfo->shdr = (FAR Elf32_Shdr*)kmalloc(shdrsize);
- if (!loadinfo->shdr)
- {
- bdbg("Failed to allocate the section header table. Size: %ld\n", (long)shdrsize);
- return -ENOMEM;
- }
-
- /* Read the section header table into memory */
-
- ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->shdr, shdrsize, loadinfo->ehdr.e_shoff);
- if (ret < 0)
- {
- bdbg("Failed to read section header table: %d\n", ret);
- }
-
- return ret;
-}
-
-/****************************************************************************
* Name: elf_allocsize
*
* Description:
@@ -292,7 +236,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
/* Find static constructors. */
-#ifdef CONFIG_ELF_CONSTRUCTORS
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
ret = elf_loadctors(loadinfo);
if (ret < 0)
{
diff --git a/nuttx/binfmt/libelf/libelf_sections.c b/nuttx/binfmt/libelf/libelf_sections.c
new file mode 100644
index 000000000..c41793544
--- /dev/null
+++ b/nuttx/binfmt/libelf/libelf_sections.c
@@ -0,0 +1,284 @@
+/****************************************************************************
+ * binfmt/libelf/libelf_sections.c
+ *
+ * Copyright (C) 2012 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/elf.h>
+
+#include "libelf.h"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_sectname
+ *
+ * Description:
+ * Get the symbol name in loadinfo->iobuffer[].
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static inline int elf_sectname(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const Elf32_Shdr *shdr)
+{
+ FAR Elf32_Shdr *shstr;
+ FAR uint8_t *buffer;
+ off_t offset;
+ size_t readlen;
+ size_t bytesread;
+ int shstrndx;
+ int ret;
+
+ /* Get the section header table index of the entry associated with the
+ * section name string table. If the file has no section name string table,
+ * this member holds the value SH_UNDEF.
+ */
+
+ shstrndx = loadinfo->ehdr.e_shstrndx;
+ if (shstrndx == SHN_UNDEF)
+ {
+ bdbg("No section header string table\n");
+ return -EINVAL;
+ }
+
+ /* Get the section name string table section header */
+
+ shstr = &loadinfo->shdr[shstrndx];
+
+ /* Get the file offset to the string that is the name of the section. This
+ * is the sum of:
+ *
+ * shstr->sh_offset: The file offset to the first byte of the section
+ * header string table data.
+ * shdr->sh_name: The offset to the name of the section in the section
+ * name table
+ */
+
+ offset = shstr->sh_offset + shdr->sh_name;
+
+ /* Loop until we get the entire section name into memory */
+
+ buffer = loadinfo->iobuffer;
+ bytesread = 0;
+
+ for (;;)
+ {
+ /* Get the number of bytes to read */
+
+ readlen = loadinfo->buflen - bytesread;
+ if (offset + readlen > loadinfo->filelen)
+ {
+ readlen = loadinfo->filelen - offset;
+ if (readlen <= 0)
+ {
+ bdbg("At end of file\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Read that number of bytes into the array */
+
+ buffer = &loadinfo->iobuffer[bytesread];
+ ret = elf_read(loadinfo, buffer, readlen, offset);
+ if (ret < 0)
+ {
+ bdbg("Failed to read section name\n");
+ return ret;
+ }
+
+ bytesread += readlen;
+
+ /* Did we read the NUL terminator? */
+
+ if (memchr(buffer, '\0', readlen) != NULL)
+ {
+ /* Yes, the buffer contains a NUL terminator. */
+
+ return OK;
+ }
+
+ /* No.. then we have to read more */
+
+ ret = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR);
+ if (ret < 0)
+ {
+ bdbg("elf_reallocbuffer failed: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* We will not get here */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: elf_loadshdrs
+ *
+ * Description:
+ * Loads section headers into memory.
+ *
+ * Returned Value:
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo)
+{
+ size_t shdrsize;
+ int ret;
+
+ DEBUGASSERT(loadinfo->shdr == NULL);
+
+ /* Verify that there are sections */
+
+ if (loadinfo->ehdr.e_shnum < 1)
+ {
+ bdbg("No sections(?)\n");
+ return -EINVAL;
+ }
+
+ /* Get the total size of the section header table */
+
+ shdrsize = (size_t)loadinfo->ehdr.e_shentsize * (size_t)loadinfo->ehdr.e_shnum;
+ if(loadinfo->ehdr.e_shoff + shdrsize > loadinfo->filelen)
+ {
+ bdbg("Insufficent space in file for section header table\n");
+ return -ESPIPE;
+ }
+
+ /* Allocate memory to hold a working copy of the sector header table */
+
+ loadinfo->shdr = (FAR Elf32_Shdr*)kmalloc(shdrsize);
+ if (!loadinfo->shdr)
+ {
+ bdbg("Failed to allocate the section header table. Size: %ld\n", (long)shdrsize);
+ return -ENOMEM;
+ }
+
+ /* Read the section header table into memory */
+
+ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->shdr, shdrsize, loadinfo->ehdr.e_shoff);
+ if (ret < 0)
+ {
+ bdbg("Failed to read section header table: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: elf_findsection
+ *
+ * Description:
+ * A section by its name.
+ *
+ * Input Parameters:
+ * loadinfo - Load state information
+ * sectname - Name of the section to find
+ *
+ * Returned Value:
+ * On success, the index to the section is returned; A negated errno value
+ * is returned on failure.
+ *
+ ****************************************************************************/
+
+int elf_findsection(FAR struct elf_loadinfo_s *loadinfo,
+ FAR const char *sectname)
+{
+ FAR const Elf32_Shdr *shdr;
+ int ret;
+ int i;
+
+ /* Search through the shdr[] array in loadinfo for a section named 'sectname' */
+
+ for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
+ {
+ /* Get the name of this section */
+
+ shdr = &loadinfo->shdr[i];
+ ret = elf_sectname(loadinfo, shdr);
+ if (ret < 0)
+ {
+ bdbg("elf_sectname failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Check if the name of this section is 'sectname' */
+
+ bvdbg("%d. Comparing \"%s\" and .\"%s\"\n",
+ i, loadinfo->iobuffer, sectname);
+
+ if (strcmp((FAR const char *)loadinfo->iobuffer, sectname) == 0)
+ {
+ /* We found it... return the index */
+
+ return i;
+ }
+ }
+
+ /* We failed to find a section with this name. */
+
+ return -ENOENT;
+}
diff --git a/nuttx/binfmt/libelf/libelf_uninit.c b/nuttx/binfmt/libelf/libelf_uninit.c
index 06bb89681..3ec6f6c61 100644
--- a/nuttx/binfmt/libelf/libelf_uninit.c
+++ b/nuttx/binfmt/libelf/libelf_uninit.c
@@ -115,15 +115,6 @@ int elf_freebuffers(struct elf_loadinfo_s *loadinfo)
loadinfo->shdr = NULL;
}
-#ifdef CONFIG_ELF_CONSTRUCTORS
- if (loadinfo->ctors)
- {
- kfree((FAR void *)loadinfo->ctors);
- loadinfo->ctors = NULL;
- loadinfo->nctors = 0;
- }
-#endif
-
if (loadinfo->iobuffer)
{
kfree((FAR void *)loadinfo->iobuffer);
diff --git a/nuttx/binfmt/libelf/libelf_unload.c b/nuttx/binfmt/libelf/libelf_unload.c
index d7a882711..8102f7bf2 100644
--- a/nuttx/binfmt/libelf/libelf_unload.c
+++ b/nuttx/binfmt/libelf/libelf_unload.c
@@ -91,6 +91,26 @@ int elf_unload(struct elf_loadinfo_s *loadinfo)
loadinfo->allocsize = 0;
}
+ /* Release any allocated constructor memory */
+
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ if (loadinfo->ctors)
+ {
+ /* In the old ABI, the .ctors section is not make for allocation. In
+ * that case, we need to free the working buffer that was used to hold
+ * the constructors.
+ */
+
+ if (!loadinfo->newabi)
+ {
+ kfree((FAR void *)loadinfo->ctors);
+ }
+
+ loadinfo->ctors = NULL;
+ loadinfo->nctors = 0;
+ }
+#endif
+
return OK;
}
diff --git a/nuttx/binfmt/libnxflat/libnxflat_load.c b/nuttx/binfmt/libnxflat/libnxflat_load.c
index 02f035072..b6693ea36 100644
--- a/nuttx/binfmt/libnxflat/libnxflat_load.c
+++ b/nuttx/binfmt/libnxflat/libnxflat_load.c
@@ -62,24 +62,6 @@
* Private Constant Data
****************************************************************************/
-#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BINFMT)
-static const char g_relocrel32i[] = "RELOC_REL32I";
-static const char g_relocrel32d[] = "RELOC_REL32D";
-static const char g_relocabs32[] = "RELOC_AB32";
-static const char g_undefined[] = "UNDEFINED";
-
-static const char *g_reloctype[] =
-{
- g_relocrel32i,
- g_relocrel32d,
- g_relocabs32,
- g_undefined
-};
-# define RELONAME(rl) g_reloctype[NXFLAT_RELOC_TYPE(rl)]
-#else
-# define RELONAME(rl) "(no name)"
-#endif
-
/****************************************************************************
* Private Functions
****************************************************************************/
diff --git a/nuttx/binfmt/nxflat.c b/nuttx/binfmt/nxflat.c
index 8d0ecfdcd..5973a96a9 100644
--- a/nuttx/binfmt/nxflat.c
+++ b/nuttx/binfmt/nxflat.c
@@ -181,16 +181,18 @@ static int nxflat_loadbinary(struct binary_s *binp)
goto errout_with_load;
}
- /* Return the load information */
+ /* Return the load information. By convention, D-space address
+ * space is stored as the first allocated memory.
+ */
binp->entrypt = (main_t)(loadinfo.ispace + loadinfo.entryoffs);
- binp->ispace = (void*)loadinfo.ispace;
- binp->dspace = (void*)loadinfo.dspace;
- binp->isize = loadinfo.isize;
+ binp->mapped = (void*)loadinfo.ispace;
+ binp->alloc[0] = (void*)loadinfo.dspace;
+ binp->mapsize = loadinfo.isize;
binp->stacksize = loadinfo.stacksize;
nxflat_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt,
- MIN(binp->isize - loadinfo.entryoffs,512));
+ MIN(loadinfo.isize - loadinfo.entryoffs, 512));
nxflat_uninit(&loadinfo);
return OK;
diff --git a/nuttx/configs/stm32f4discovery/elf/Make.defs b/nuttx/configs/stm32f4discovery/elf/Make.defs
index 7df9b13da..035a03e71 100644
--- a/nuttx/configs/stm32f4discovery/elf/Make.defs
+++ b/nuttx/configs/stm32f4discovery/elf/Make.defs
@@ -160,8 +160,8 @@ LDNXFLATFLAGS = -e main -s 2048
# ELF module definitions
-CELFFLAGS = $(CFLAGS) -mlong-calls
-CXXELFFLAGS = $(CXXFLAGS) -mlong-calls
+CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs
+CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs
LDELFFLAGS = -r -e main
ifeq ($(WINTOOL),y)
diff --git a/nuttx/configs/stm32f4discovery/elf/defconfig b/nuttx/configs/stm32f4discovery/elf/defconfig
index 59c221a0c..67f5bf365 100644
--- a/nuttx/configs/stm32f4discovery/elf/defconfig
+++ b/nuttx/configs/stm32f4discovery/elf/defconfig
@@ -388,7 +388,7 @@ CONFIG_ELF_ALIGN_LOG2=2
CONFIG_ELF_STACKSIZE=2048
CONFIG_ELF_BUFFERSIZE=128
CONFIG_ELF_BUFFERINCR=32
-CONFIG_ELF_CONSTRUCTORS=y
+CONFIG_BINFMT_CONSTRUCTORS=y
CONFIG_SYMTAB_ORDEREDBYNAME=y
#
diff --git a/nuttx/configs/stm32f4discovery/scripts/gnu-elf.ld b/nuttx/configs/stm32f4discovery/scripts/gnu-elf.ld
index 0153cf5fa..1f29f02f5 100644
--- a/nuttx/configs/stm32f4discovery/scripts/gnu-elf.ld
+++ b/nuttx/configs/stm32f4discovery/scripts/gnu-elf.ld
@@ -51,8 +51,8 @@ SECTIONS
*/
*(.gnu.linkonce.t.*)
- *(.init)
- *(.fini)
+ *(.init) /* Old ABI */
+ *(.fini) /* Old ABI */
_etext = . ;
}
@@ -86,15 +86,17 @@ SECTIONS
.ctors :
{
- _sctros = . ;
- *(.ctors)
+ _sctors = . ;
+ *(.ctors) /* Old ABI: Unallocated */
+ *(.init_array) /* New ABI: Allocated */
_edtors = . ;
}
- .ctors :
+ .dtors :
{
_sdtors = . ;
- *(.dtors)
+ *(.dtors) /* Old ABI: Unallocated */
+ *(.fini_array) /* New ABI: Allocated */
_edtors = . ;
}
diff --git a/nuttx/include/nuttx/binfmt/binfmt.h b/nuttx/include/nuttx/binfmt/binfmt.h
index 82e5f3557..0c18bfc49 100644
--- a/nuttx/include/nuttx/binfmt/binfmt.h
+++ b/nuttx/include/nuttx/binfmt/binfmt.h
@@ -49,9 +49,15 @@
* Pre-processor Definitions
****************************************************************************/
+#define BINFMT_NALLOC 2
+
/****************************************************************************
* Public Types
****************************************************************************/
+/* The type of one C++ constructor or destructor */
+
+typedef FAR void (*elf_ctor_t)(void);
+typedef FAR void (*elf_dtor_t)(void);
/* This describes the file to be loaded */
@@ -70,9 +76,15 @@ struct binary_s
*/
main_t entrypt; /* Entry point into a program module */
- FAR void *ispace; /* Memory-mapped, I-space (.text) address */
- FAR struct dspace_s *dspace; /* Address of the allocated .data/.bss space */
- size_t isize; /* Size of the I-space region (needed for munmap) */
+ FAR void *mapped; /* Memory-mapped, address space */
+ FAR void *alloc[BINFMT_NALLOC]; /* Allocated address spaces */
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ elf_ctor_t *ctors; /* Pointer to a list of constructors */
+ elf_dtor_t *dtors; /* Pointer to a list of destructors */
+ uint16_t nctors; /* Number of constructors in the list */
+ uint16_t ndtors; /* Number of destructors in the list */
+#endif
+ size_t mapsize; /* Size of the mapped address region (needed for munmap) */
size_t stacksize; /* Size of the stack in bytes (unallocated) */
};
@@ -151,7 +163,12 @@ EXTERN int load_module(FAR struct binary_s *bin);
*
* Description:
* Unload a (non-executing) module from memory. If the module has
- * been started (via exec_module), calling this will be fatal.
+ * been started (via exec_module) and has not exited, calling this will
+ * be fatal.
+ *
+ * However, this function must be called after the module exist. How
+ * this is done is up to your logic. Perhaps you register it to be
+ * called by on_exit()?
*
* Returned Value:
* This is a NuttX internal function so it follows the convention that
diff --git a/nuttx/include/nuttx/binfmt/elf.h b/nuttx/include/nuttx/binfmt/elf.h
index 4770d82a3..2e3cb8623 100644
--- a/nuttx/include/nuttx/binfmt/elf.h
+++ b/nuttx/include/nuttx/binfmt/elf.h
@@ -43,10 +43,13 @@
#include <nuttx/config.h>
#include <sys/types.h>
+
#include <stdint.h>
#include <stdbool.h>
#include <elf32.h>
+#include <nuttx/binfmt/binfmt.h>
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -59,9 +62,6 @@
/****************************************************************************
* Public Types
****************************************************************************/
-/* The type of one C++ constructor */
-
-typedef FAR void (*elf_ctor_t)(void);
/* This struct provides a desciption of the currently loaded instantiation
* of an ELF binary.
@@ -72,17 +72,18 @@ struct elf_loadinfo_s
uintptr_t alloc; /* Allocated memory with the ELF file is loaded */
size_t allocsize; /* Size of the memory allocation */
off_t filelen; /* Length of the entire ELF file */
- int filfd; /* Descriptor for the file being loaded */
-#ifdef CONFIG_ELF_CONSTRUCTORS
- elf_ctor_t ctors; /* Pointer to a list of constructors */
+ Elf32_Ehdr ehdr; /* Buffered ELF file header */
+ FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */
+ uint8_t *iobuffer; /* File I/O buffer */
+#ifdef CONFIG_BINFMT_CONSTRUCTORS
+ elf_ctor_t *ctors; /* Pointer to a list of constructors */
+ bool newabi; /* True: ctors in 'alloc' */
uint16_t nctors; /* Number of constructors */
#endif
uint16_t symtabidx; /* Symbol table section index */
uint16_t strtabidx; /* String table section index */
uint16_t buflen; /* size of iobuffer[] */
- Elf32_Ehdr ehdr; /* Buffered ELF file header */
- FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */
- uint8_t *iobuffer; /* File I/O buffer */
+ int filfd; /* Descriptor for the file being loaded */
};
/****************************************************************************