diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-10-29 19:32:05 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-10-29 19:32:05 +0000 |
commit | 9e45144d3ad1420908cfdf84306c76f637829023 (patch) | |
tree | 63a4ac04f182a282aac2d649973c99285b12cad5 | |
parent | ade5fb42679b7e890f29487ca850c65f9944fa1e (diff) | |
download | nuttx-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
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 */ }; /**************************************************************************** |