From 71fad980c5dfe057dd380a05f1ca1e0bfad2ef1f Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 29 Oct 2012 00:52:23 +0000 Subject: [PATCH] Finish implemention of ELF loader static constructor support. Still some issues. git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5272 42af7a65-404d-4744-a932-0658087f49c3 --- apps/examples/README.txt | 2 + apps/examples/elf/tests/Makefile | 8 +- apps/examples/elf/tests/hello++/Makefile | 116 -------- apps/examples/elf/tests/hello++/hello++1.cpp | 60 ---- apps/examples/elf/tests/hello++/hello++2.cpp | 123 --------- apps/examples/elf/tests/hello++/hello++3.cpp | 132 --------- apps/examples/elf/tests/hello++/hello++4.cpp | 150 ---------- nuttx/arch/arm/src/armv7-m/up_elf.c | 2 +- nuttx/binfmt/elf.c | 1 + nuttx/binfmt/libelf/Make.defs | 2 +- nuttx/binfmt/libelf/libelf.h | 45 ++- nuttx/binfmt/libelf/libelf_bind.c | 15 +- nuttx/binfmt/libelf/libelf_ctors.c | 274 +++++++++++++++++-- nuttx/binfmt/libelf/libelf_iobuffer.c | 136 +++++++++ nuttx/binfmt/libelf/libelf_load.c | 29 +- nuttx/binfmt/libelf/libelf_symbols.c | 17 +- nuttx/binfmt/libelf/libelf_uninit.c | 50 ++++ nuttx/binfmt/libelf/libelf_unload.c | 21 +- nuttx/configs/stm32f4discovery/elf/Make.defs | 2 + nuttx/configs/stm32f4discovery/elf/defconfig | 270 +----------------- nuttx/include/nuttx/binfmt/elf.h | 5 +- 21 files changed, 532 insertions(+), 928 deletions(-) delete mode 100644 apps/examples/elf/tests/hello++/Makefile delete mode 100644 apps/examples/elf/tests/hello++/hello++1.cpp delete mode 100644 apps/examples/elf/tests/hello++/hello++2.cpp delete mode 100644 apps/examples/elf/tests/hello++/hello++3.cpp delete mode 100644 apps/examples/elf/tests/hello++/hello++4.cpp create mode 100644 nuttx/binfmt/libelf/libelf_iobuffer.c diff --git a/apps/examples/README.txt b/apps/examples/README.txt index abf95e208d..907467bb17 100644 --- a/apps/examples/README.txt +++ b/apps/examples/README.txt @@ -323,6 +323,8 @@ examples/elf CELFFLAGS = $(CFLAGS) -mlong-calls + Similarly for C++ flags which must be provided in CXXELFFLAGS. + 2. Your top-level nuttx/Make.defs file must alos include an approproate definition, LDELFFLAGS, to generate a relocatable ELF object. With GNU LD, this should include '-r' and '-e main' (or _main on some platforms). diff --git a/apps/examples/elf/tests/Makefile b/apps/examples/elf/tests/Makefile index f834f6c780..d2192cb1e4 100644 --- a/apps/examples/elf/tests/Makefile +++ b/apps/examples/elf/tests/Makefile @@ -33,13 +33,15 @@ # ############################################################################ -# Most of these do no build yet +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs -ALL_SUBDIRS = errno hello hello++ longjmp mutex pthread signal task struct +ALL_SUBDIRS = errno hello helloxx longjmp mutex pthread signal task struct BUILD_SUBDIRS = errno hello task struct ifeq ($(CONFIG_HAVE_CXX),y) -BUILD_SUBDIRS += hello++ +BUILD_SUBDIRS += helloxx endif ifeq ($(CONFIG_EXAMPLES_ELF_LONGJMP),y) diff --git a/apps/examples/elf/tests/hello++/Makefile b/apps/examples/elf/tests/hello++/Makefile deleted file mode 100644 index 9de52cfa10..0000000000 --- a/apps/examples/elf/tests/hello++/Makefile +++ /dev/null @@ -1,116 +0,0 @@ -############################################################################ -# examples/elf/tests/hello/Makefile -# -# Copyright (C) 2012 Gregory Nutt. All rights reserved. -# Author: Gregory Nutt -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# 3. Neither the name NuttX nor the names of its contributors may be -# used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -############################################################################ - --include $(TOPDIR)/.config --include $(TOPDIR)/Make.defs - -BIN1 = hello++1 -BIN2 = hello++2 -BIN3 = hello++3 -#BIN4 = hello++4 -ALL_BIN = $(BIN1) $(BIN2) $(BIN3) $(BIN4) - -SRCS1 = $(BIN1).c -OBJS1 = $(SRCS1:.c=.o) - -SRCS2 = $(BIN2).c -OBJS2 = $(SRCS2:.c=.o) - -SRCS3 = $(BIN3).c -OBJS3 = $(SRCS3:.c=.o) - -#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 $(CXXFLAGS) $< -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 - -$(BIN3): $(OBJS3) - @echo "LD: $<" - @$(LD) $(LDELFFLAGS) -o $@ $^ - -# 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) - @install -D $(BIN3) $(ROMFS_DIR)/$(BIN3) -# @install -D $(BIN4) $(ROMFS_DIR)/$(BIN4) - - - - - - - diff --git a/apps/examples/elf/tests/hello++/hello++1.cpp b/apps/examples/elf/tests/hello++/hello++1.cpp deleted file mode 100644 index 22a7281886..0000000000 --- a/apps/examples/elf/tests/hello++/hello++1.cpp +++ /dev/null @@ -1,60 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// examples/elf/tests/hello++/hello++1.c -// -// Copyright (C) 2012 Gregory Nutt. All rights reserved. -// Author: Gregory Nutt -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// 3. Neither the name NuttX nor the names of its contributors may be -// used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -///////////////////////////////////////////////////////////////////////////// -// -// 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 - -///////////////////////////////////////////////////////////////////////////// -// Public Functions -///////////////////////////////////////////////////////////////////////////// - -int main(int argc, char **argv) -{ - printf("Hello, World!\n"); - return 0; -} diff --git a/apps/examples/elf/tests/hello++/hello++2.cpp b/apps/examples/elf/tests/hello++/hello++2.cpp deleted file mode 100644 index a8ba589bd3..0000000000 --- a/apps/examples/elf/tests/hello++/hello++2.cpp +++ /dev/null @@ -1,123 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// examples/elf/tests/hello++/hello++2.c -// -// Copyright (C) 2012 Gregory Nutt. All rights reserved. -// Author: Gregory Nutt -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// 3. Neither the name NuttX nor the names of its contributors may be -// used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -///////////////////////////////////////////////////////////////////////////// -// -// 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 - -///////////////////////////////////////////////////////////////////////////// -// 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/hello++/hello++3.cpp b/apps/examples/elf/tests/hello++/hello++3.cpp deleted file mode 100644 index eedaa6df0c..0000000000 --- a/apps/examples/elf/tests/hello++/hello++3.cpp +++ /dev/null @@ -1,132 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// examples/elf/tests/hello++/hello++3.c -// -// Copyright (C) 2012 Gregory Nutt. All rights reserved. -// Author: Gregory Nutt -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// 3. Neither the name NuttX nor the names of its contributors may be -// used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -///////////////////////////////////////////////////////////////////////////// -// -// 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 - -///////////////////////////////////////////////////////////////////////////// -// 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/hello++/hello++4.cpp b/apps/examples/elf/tests/hello++/hello++4.cpp deleted file mode 100644 index 1a9f2e28b7..0000000000 --- a/apps/examples/elf/tests/hello++/hello++4.cpp +++ /dev/null @@ -1,150 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// examples/elf/tests/hello++/hello++4.c -// -// Copyright (C) 2012 Gregory Nutt. All rights reserved. -// Author: Gregory Nutt -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// 3. Neither the name NuttX nor the names of its contributors may be -// used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -///////////////////////////////////////////////////////////////////////////// -// -// 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 -#include - -#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/armv7-m/up_elf.c b/nuttx/arch/arm/src/armv7-m/up_elf.c index 202c902b4b..1cc1fa32a2 100644 --- a/nuttx/arch/arm/src/armv7-m/up_elf.c +++ b/nuttx/arch/arm/src/armv7-m/up_elf.c @@ -282,7 +282,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym, if (offset <= (int32_t)0xff000000 || offset >= (int32_t)0x01000000) { - bdbg(" ERROR: JUMP24 [%d] relocation out of range, offset=%08lx\n", + bdbg(" ERROR: JUMP24 [%d] relocation out of range, branch taget=%08lx\n", ELF32_R_TYPE(rel->r_info), offset); return -EINVAL; diff --git a/nuttx/binfmt/elf.c b/nuttx/binfmt/elf.c index 9a0ac1873f..57123ed95d 100644 --- a/nuttx/binfmt/elf.c +++ b/nuttx/binfmt/elf.c @@ -116,6 +116,7 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo) bdbg(" filelen: %ld\n", (long)loadinfo->filelen); #ifdef CONFIG_ELF_CONSTRUCTORS bdbg(" ctors: %08lx\n", (long)loadinfo->ctors); + bdbg(" nctors: %d\n", loadinfo->nctors); #endif bdbg(" filfd: %d\n", loadinfo->filfd); bdbg(" symtabidx: %d\n", loadinfo->symtabidx); diff --git a/nuttx/binfmt/libelf/Make.defs b/nuttx/binfmt/libelf/Make.defs index a70a127f80..cf2507a995 100644 --- a/nuttx/binfmt/libelf/Make.defs +++ b/nuttx/binfmt/libelf/Make.defs @@ -43,7 +43,7 @@ BINFMT_CSRCS += elf.c 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_bind.c libelf_symbols.c libelf_iobuffer.c ifeq ($(CONFIG_ELF_CONSTRUCTORS),y) BINFMT_CSRCS += libelf_ctors.c diff --git a/nuttx/binfmt/libelf/libelf.h b/nuttx/binfmt/libelf/libelf.h index 0fb1362dcd..0d13515cc9 100644 --- a/nuttx/binfmt/libelf/libelf.h +++ b/nuttx/binfmt/libelf/libelf.h @@ -141,6 +141,49 @@ int elf_readsym(FAR struct elf_loadinfo_s *loadinfo, int index, int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym, FAR const struct symtab_s *exports, int nexports); +/**************************************************************************** + * Name: elf_freebuffers + * + * Description: + * Release all working buffers. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_freebuffers(FAR struct elf_loadinfo_s *loadinfo); + +/**************************************************************************** + * Name: elf_allocbuffer + * + * Description: + * Perform the initial allocation of the I/O buffer, if it has not already + * been allocated. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_allocbuffer(FAR struct elf_loadinfo_s *loadinfo); + +/**************************************************************************** + * Name: elf_reallocbuffer + * + * Description: + * Increase the size of I/O buffer by the specified buffer increment. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment); + /**************************************************************************** * Name: elf_findctors * @@ -157,7 +200,7 @@ int elf_symvalue(FAR struct elf_loadinfo_s *loadinfo, FAR Elf32_Sym *sym, ****************************************************************************/ #ifdef CONFIG_ELF_CONSTRUCTORS -int elf_findctors(FAR struct elf_loadinfo_s *loadinfo); +int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo); #endif /**************************************************************************** diff --git a/nuttx/binfmt/libelf/libelf_bind.c b/nuttx/binfmt/libelf/libelf_bind.c index 54ea8f1f04..ef1b4fc8fd 100644 --- a/nuttx/binfmt/libelf/libelf_bind.c +++ b/nuttx/binfmt/libelf/libelf_bind.c @@ -46,7 +46,6 @@ #include #include -#include #include #include @@ -247,17 +246,16 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo, return ret; } - /* Allocate an I/O buffer. This buffer is used only by elf_symname() to + /* Allocate an I/O buffer. This buffer is used by elf_symname() to * accumulate the variable length symbol name. */ - loadinfo->iobuffer = (FAR uint8_t *)kmalloc(CONFIG_ELF_BUFFERSIZE); - if (!loadinfo->iobuffer) + ret = elf_allocbuffer(loadinfo); + if (ret < 0) { - bdbg("Failed to allocate an I/O buffer\n"); + bdbg("elf_allocbuffer failed: %d\n", ret); return -ENOMEM; } - loadinfo->buflen = CONFIG_ELF_BUFFERSIZE; /* Process relocations in every allocated section */ @@ -303,11 +301,6 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo, arch_flushicache((FAR void*)loadinfo->alloc, loadinfo->allocsize); #endif - /* Free the I/O buffer */ - - kfree(loadinfo->iobuffer); - loadinfo->iobuffer = NULL; - loadinfo->buflen = 0; return ret; } diff --git a/nuttx/binfmt/libelf/libelf_ctors.c b/nuttx/binfmt/libelf/libelf_ctors.c index e8b095bb78..c53923d44f 100644 --- a/nuttx/binfmt/libelf/libelf_ctors.c +++ b/nuttx/binfmt/libelf/libelf_ctors.c @@ -39,11 +39,15 @@ #include +#include +#include +#include #include +#include #include -#include "libelf" +#include "libelf.h" #ifdef CONFIG_ELF_CONSTRUCTORS @@ -55,8 +59,6 @@ * Private Types ****************************************************************************/ -typedef FAR void (*ctor_t)(void); - /**************************************************************************** * Private Constant Data ****************************************************************************/ @@ -66,9 +68,111 @@ typedef FAR void (*ctor_t)(void); ****************************************************************************/ /**************************************************************************** - * Public 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; +} + /**************************************************************************** * Name: elf_findctors * @@ -79,27 +183,157 @@ typedef FAR void (*ctor_t)(void); * 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 + ****************************************************************************/ + +/**************************************************************************** + * Name: elf_loadctors + * + * Description: + * Load points to static constructors into an in-memory array. + * + * Input Parameters: + * loadinfo - Load state information + * + * Returned Value: * 0 (OK) is returned on success and a negated errno is returned on * failure. * ****************************************************************************/ -int elf_findctors(FAR struct elf_loadinfo_s *loadinfo) +int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo) { - /* Search through the shdr[] array in loadinfo for a section named .ctors */ -#warning "Missing logic" + FAR Elf32_Shdr *shdr; + size_t ctorsize; + int ctoridx; + int ret; + int i; - /* Get the address of the beginning of the constructros from the sh_addr - * field of the section. Save that in the ctors field of the loadinfo - * structure. + DEBUGASSERT(loadinfo->ctors == NULL); + + /* Allocate an I/O buffer. This buffer is used by elf_sectname() to + * accumulate the variable length symbol name. */ -#warning "Missing logic" - /* Get the number of constructors from the sh_size field of the section. - * Save that number in the nctors field of the loadinfo structure. - */ -#warning "Missing logic" - return -ENOSYS; + ret = elf_allocbuffer(loadinfo); + if (ret < 0) + { + bdbg("elf_allocbuffer failed: %d\n", ret); + return -ENOMEM; + } + + /* Find the index to the section named ".ctors" */ + + ctoridx = elf_findctors(loadinfo); + 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); + return ret == -ENOENT ? OK : ret; + } + + /* Now we can get a pointer to the .ctor section in the section header + * table. + */ + + shdr = &loadinfo->shdr[ctoridx]; + + /* Allocate memory to hold a copy of the .ctor section */ + + ctorsize = shdr->sh_size; + loadinfo->nctors = ctorsize / sizeof(elf_ctor_t); + + bvdbg("ctoridx=%d ctorsize=%d sizeof(elf_ctor_t)=%d nctors=%d\n", + ctoridx, ctorsize, sizeof(elf_ctor_t), loadinfo->nctors); + + /* Check if there are any constructors. It is not an error if there + * are none. + */ + + if (loadinfo->nctors > 0) + { + /* 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; + } + + /* Read the section header table into memory */ + + ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->ctors, ctorsize, + shdr->sh_offset); + if (ret < 0) + { + bdbg("Failed to allocate .ctors: %d\n", ret); + } + + /* Fix up all of the .ctor addresses */ + + for (i = 0; i < loadinfo->nctors; i++) + { + FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]); + + bvdbg("ctor %d: %08lx + %08lx = %08lx\n", i, + *ptr, loadinfo->alloc, *ptr + loadinfo->alloc); + + *ptr += loadinfo->alloc; + } + } + + return OK; } /**************************************************************************** @@ -119,16 +353,20 @@ int elf_findctors(FAR struct elf_loadinfo_s *loadinfo) int elf_doctors(FAR struct elf_loadinfo_s *loadinfo) { - ctor_t ctor = (ctor_t)loadinfo->ctors; + elf_ctor_t ctor = (elf_ctor_t)loadinfo->ctors; int i; /* Execute each constructor */ for (i = 0; i < loadinfo->nctors; i++) { + bvdbg("Calling ctor %d at %p\n", i, (FAR void *)ctor); + ctor(); ctor++; } + + return OK; } -#endif /* CONFIG_ELF_CONSTRUCTORS +#endif /* CONFIG_ELF_CONSTRUCTORS */ diff --git a/nuttx/binfmt/libelf/libelf_iobuffer.c b/nuttx/binfmt/libelf/libelf_iobuffer.c new file mode 100644 index 0000000000..ead99ca099 --- /dev/null +++ b/nuttx/binfmt/libelf/libelf_iobuffer.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * binfmt/libelf/elf_iobuffer.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "libelf.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: elf_allocbuffer + * + * Description: + * Perform the initial allocation of the I/O buffer, if it has not already + * been allocated. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_allocbuffer(FAR struct elf_loadinfo_s *loadinfo) +{ + /* Has a buffer been allocated> */ + + if (!loadinfo->iobuffer) + { + /* No.. allocate one now */ + + loadinfo->iobuffer = (FAR uint8_t *)kmalloc(CONFIG_ELF_BUFFERSIZE); + if (!loadinfo->iobuffer) + { + bdbg("Failed to allocate an I/O buffer\n"); + return -ENOMEM; + } + + loadinfo->buflen = CONFIG_ELF_BUFFERSIZE; + } + + return OK; +} + +/**************************************************************************** + * Name: elf_reallocbuffer + * + * Description: + * Increase the size of I/O buffer by the specified buffer increment. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_reallocbuffer(FAR struct elf_loadinfo_s *loadinfo, size_t increment) +{ + FAR void *buffer; + size_t newsize; + + /* Get the new size of the allocation */ + + newsize = loadinfo->buflen + increment; + + /* And perform the reallocation */ + + buffer = krealloc((FAR void *)loadinfo->iobuffer, newsize); + if (!buffer) + { + bdbg("Failed to reallocate the I/O buffer\n"); + return -ENOMEM; + } + + /* Save the new buffer info */ + + loadinfo->iobuffer = buffer; + loadinfo->buflen = newsize; + return OK; +} + diff --git a/nuttx/binfmt/libelf/libelf_load.c b/nuttx/binfmt/libelf/libelf_load.c index 6526004f76..505e2c8131 100644 --- a/nuttx/binfmt/libelf/libelf_load.c +++ b/nuttx/binfmt/libelf/libelf_load.c @@ -126,14 +126,8 @@ static inline int elf_loadshdrs(FAR struct elf_loadinfo_s *loadinfo) if (ret < 0) { bdbg("Failed to read section header table: %d\n", ret); - goto errout_with_alloc; } - return OK; - -errout_with_alloc: - kfree(loadinfo->shdr); - loadinfo->shdr = 0; return ret; } @@ -233,7 +227,7 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) if (ret < 0) { bdbg("Failed to read section %d: %d\n", i, ret); - goto errout_with_alloc; + return ret; } } @@ -248,11 +242,6 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo) } return OK; - -errout_with_alloc: - kfree((FAR void*)loadinfo->alloc); - loadinfo->alloc = 0; - return ret; } /**************************************************************************** @@ -285,7 +274,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) if (ret < 0) { bdbg("elf_loadshdrs failed: %d\n", ret); - return ret; + goto errout_with_buffers; } /* Determine total size to allocate */ @@ -298,16 +287,17 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) if (ret < 0) { bdbg("elf_loadfile failed: %d\n", ret); - goto errout_with_shdrs; + goto errout_with_buffers; } /* Find static constructors. */ #ifdef CONFIG_ELF_CONSTRUCTORS - ret = elf_findctors(loadinfo); + ret = elf_loadctors(loadinfo); + if (ret < 0) { - bdbg("elf_findctors failed: %d\n", ret); - goto errout_with_shdrs; + bdbg("elf_loadctors failed: %d\n", ret); + goto errout_with_buffers; } #endif @@ -315,9 +305,8 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo) /* Error exits */ -errout_with_shdrs: - kfree(loadinfo->shdr); - loadinfo->shdr = NULL; +errout_with_buffers: + elf_freebuffers(loadinfo); return ret; } diff --git a/nuttx/binfmt/libelf/libelf_symbols.c b/nuttx/binfmt/libelf/libelf_symbols.c index 123f9f77f5..2d94b11af0 100644 --- a/nuttx/binfmt/libelf/libelf_symbols.c +++ b/nuttx/binfmt/libelf/libelf_symbols.c @@ -101,7 +101,6 @@ static int elf_symname(FAR struct elf_loadinfo_s *loadinfo, /* Loop until we get the entire symbol name into memory */ - buffer = loadinfo->iobuffer; bytesread = 0; for (;;) @@ -125,7 +124,7 @@ static int elf_symname(FAR struct elf_loadinfo_s *loadinfo, ret = elf_read(loadinfo, buffer, readlen, offset); if (ret < 0) { - bdbg("Failed to read symbol name\n"); + bdbg("elf_read failed: %d\n", ret); return ret; } @@ -142,18 +141,12 @@ static int elf_symname(FAR struct elf_loadinfo_s *loadinfo, /* No.. then we have to read more */ - buffer = realloc((FAR void *)loadinfo->iobuffer, - loadinfo->buflen + CONFIG_ELF_BUFFERINCR); - if (!buffer) + ret = elf_reallocbuffer(loadinfo, CONFIG_ELF_BUFFERINCR); + if (ret < 0) { - bdbg("Failed to reallocate the I/O buffer\n"); - return -ENOMEM; + bdbg("elf_reallocbuffer failed: %d\n", ret); + return ret; } - - /* Save the new buffer info */ - - loadinfo->iobuffer = buffer; - loadinfo->buflen += CONFIG_ELF_BUFFERINCR; } /* We will not get here */ diff --git a/nuttx/binfmt/libelf/libelf_uninit.c b/nuttx/binfmt/libelf/libelf_uninit.c index e5fa2e6c33..06bb896816 100644 --- a/nuttx/binfmt/libelf/libelf_uninit.c +++ b/nuttx/binfmt/libelf/libelf_uninit.c @@ -42,8 +42,12 @@ #include #include #include + +#include #include +#include "libelf.h" + /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ @@ -75,6 +79,12 @@ int elf_uninit(struct elf_loadinfo_s *loadinfo) { + /* Free all working buffers */ + + elf_freebuffers(loadinfo); + + /* Close the ELF file */ + if (loadinfo->filfd >= 0) { close(loadinfo->filfd); @@ -83,3 +93,43 @@ int elf_uninit(struct elf_loadinfo_s *loadinfo) return OK; } +/**************************************************************************** + * Name: elf_freebuffers + * + * Description: + * Release all working buffers. + * + * Returned Value: + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int elf_freebuffers(struct elf_loadinfo_s *loadinfo) +{ + /* Release all working allocations */ + + if (loadinfo->shdr) + { + kfree((FAR void *)loadinfo->shdr); + 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); + loadinfo->iobuffer = NULL; + loadinfo->buflen = 0; + } + + return OK; +} diff --git a/nuttx/binfmt/libelf/libelf_unload.c b/nuttx/binfmt/libelf/libelf_unload.c index 3351064079..d7a8827111 100644 --- a/nuttx/binfmt/libelf/libelf_unload.c +++ b/nuttx/binfmt/libelf/libelf_unload.c @@ -45,6 +45,8 @@ #include #include +#include "libelf.h" + /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ @@ -76,7 +78,11 @@ int elf_unload(struct elf_loadinfo_s *loadinfo) { - /* Release the all allocated memory */ + /* Free all working buffers */ + + elf_freebuffers(loadinfo); + + /* Release memory holding the relocated ELF image */ if (loadinfo->alloc) { @@ -85,19 +91,6 @@ int elf_unload(struct elf_loadinfo_s *loadinfo) loadinfo->allocsize = 0; } - if (loadinfo->shdr) - { - kfree((FAR void *)loadinfo->shdr); - loadinfo->shdr = NULL; - } - - if (loadinfo->iobuffer) - { - kfree((FAR void *)loadinfo->iobuffer); - loadinfo->iobuffer = NULL; - loadinfo->buflen = 0; - } - return OK; } diff --git a/nuttx/configs/stm32f4discovery/elf/Make.defs b/nuttx/configs/stm32f4discovery/elf/Make.defs index c64102d174..7df9b13da6 100644 --- a/nuttx/configs/stm32f4discovery/elf/Make.defs +++ b/nuttx/configs/stm32f4discovery/elf/Make.defs @@ -161,6 +161,8 @@ LDNXFLATFLAGS = -e main -s 2048 # ELF module definitions CELFFLAGS = $(CFLAGS) -mlong-calls +CXXELFFLAGS = $(CXXFLAGS) -mlong-calls + LDELFFLAGS = -r -e main ifeq ($(WINTOOL),y) LDELFFLAGS += -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld}" diff --git a/nuttx/configs/stm32f4discovery/elf/defconfig b/nuttx/configs/stm32f4discovery/elf/defconfig index 5bbef5e73a..59c221a0ca 100644 --- a/nuttx/configs/stm32f4discovery/elf/defconfig +++ b/nuttx/configs/stm32f4discovery/elf/defconfig @@ -28,6 +28,7 @@ CONFIG_INTELHEX_BINARY=y # # CONFIG_ARCH_STDBOOL_H is not set # CONFIG_ARCH_MATH_H is not set +# CONFIG_ARCH_FLOAT_H is not set # CONFIG_ARCH_STDARG_H is not set # @@ -387,7 +388,7 @@ CONFIG_ELF_ALIGN_LOG2=2 CONFIG_ELF_STACKSIZE=2048 CONFIG_ELF_BUFFERSIZE=128 CONFIG_ELF_BUFFERINCR=32 -# CONFIG_ELF_CONSTRUCTORS is not set +CONFIG_ELF_CONSTRUCTORS=y CONFIG_SYMTAB_ORDEREDBYNAME=y # @@ -397,6 +398,7 @@ CONFIG_STDIO_BUFFER_SIZE=256 CONFIG_STDIO_LINEBUFFER=y CONFIG_NUNGET_CHARS=2 CONFIG_LIB_HOMEDIR="/" +# CONFIG_LIBM is not set # CONFIG_NOPRINTF_FIELDWIDTH is not set # CONFIG_LIBC_FLOATINGPOINT is not set # CONFIG_EOL_IS_CR is not set @@ -425,264 +427,57 @@ CONFIG_HAVE_CXX=y # # Examples # - -# -# ADC Example -# - -# -# Buttons Example -# # CONFIG_EXAMPLES_BUTTONS is not set - -# -# CAN Example -# # CONFIG_EXAMPLES_CAN is not set - -# -# USB CDC/ACM Class Driver Example -# # CONFIG_EXAMPLES_CDCACM is not set - -# -# USB composite Class Driver Example -# # CONFIG_EXAMPLES_COMPOSITE is not set - -# -# DHCP Server Example -# # CONFIG_EXAMPLES_DHCPD is not set - -# -# ELF Loader Example -# CONFIG_EXAMPLES_ELF=y CONFIG_EXAMPLES_ELF_DEVMINOR=0 CONFIG_EXAMPLES_ELF_DEVPATH="/dev/ram0" - -# -# FTP Client Example -# # CONFIG_EXAMPLES_FTPC is not set - -# -# FTP Server Example -# # CONFIG_EXAMPLES_FTPD is not set - -# -# "Hello, World!" Example -# # CONFIG_EXAMPLES_HELLO is not set - -# -# "Hello, World!" C++ Example -# # CONFIG_EXAMPLES_HELLOXX is not set - -# -# USB HID Keyboard Example -# +# CONFIG_EXAMPLES_JSON is not set # CONFIG_EXAMPLES_HIDKBD is not set - -# -# IGMP Example -# # CONFIG_EXAMPLES_IGMP is not set - -# -# LCD Read/Write Example -# # CONFIG_EXAMPLES_LCDRW is not set - -# -# Memory Management Example -# # CONFIG_EXAMPLES_MM is not set - -# -# File System Mount Example -# # CONFIG_EXAMPLES_MOUNT is not set - -# -# FreeModBus Example -# # CONFIG_EXAMPLES_MODBUS is not set - -# -# Network Test Example -# # CONFIG_EXAMPLES_NETTEST is not set - -# -# NuttShell (NSH) Example -# # CONFIG_EXAMPLES_NSH is not set - -# -# NULL Example -# # CONFIG_EXAMPLES_NULL is not set - -# -# NX Graphics Example -# # CONFIG_EXAMPLES_NX is not set - -# -# NxConsole Example -# # CONFIG_EXAMPLES_NXCONSOLE is not set - -# -# NXFFS File System Example -# # CONFIG_EXAMPLES_NXFFS is not set - -# -# NXFLAT Example -# # CONFIG_EXAMPLES_NXFLAT is not set - -# -# NX Graphics "Hello, World!" Example -# # CONFIG_EXAMPLES_NXHELLO is not set - -# -# NX Graphics image Example -# # CONFIG_EXAMPLES_NXIMAGE is not set - -# -# NX Graphics lines Example -# # CONFIG_EXAMPLES_NXLINES is not set - -# -# NX Graphics Text Example -# # CONFIG_EXAMPLES_NXTEXT is not set - -# -# OS Test Example -# # CONFIG_EXAMPLES_OSTEST is not set - -# -# Pascal "Hello, World!"example -# # CONFIG_EXAMPLES_PASHELLO is not set - -# -# Pipe Example -# # CONFIG_EXAMPLES_PIPE is not set - -# -# Poll Example -# # CONFIG_EXAMPLES_POLL is not set - -# -# Pulse Width Modulation (PWM) Example -# - -# -# Quadrature Encoder Example -# # CONFIG_EXAMPLES_QENCODER is not set - -# -# RGMP Example -# # CONFIG_EXAMPLES_RGMP is not set - -# -# ROMFS Example -# # CONFIG_EXAMPLES_ROMFS is not set - -# -# sendmail Example -# # CONFIG_EXAMPLES_SENDMAIL is not set - -# -# Serial Loopback Example -# # CONFIG_EXAMPLES_SERLOOP is not set - -# -# Telnet Daemon Example -# # CONFIG_EXAMPLES_TELNETD is not set - -# -# THTTPD Web Server Example -# # CONFIG_EXAMPLES_THTTPD is not set - -# -# TIFF Generation Example -# # CONFIG_EXAMPLES_TIFF is not set - -# -# Touchscreen Example -# # CONFIG_EXAMPLES_TOUCHSCREEN is not set - -# -# UDP Example -# # CONFIG_EXAMPLES_UDP is not set - -# -# UDP Discovery Daemon Example -# - -# -# uIP Web Server Example -# # CONFIG_EXAMPLES_UIP is not set - -# -# USB Serial Test Example -# # CONFIG_EXAMPLES_USBSERIAL is not set - -# -# USB Mass Storage Class Example -# # CONFIG_EXAMPLES_USBMSC is not set - -# -# USB Serial Terminal Example -# # CONFIG_EXAMPLES_USBTERM is not set - -# -# Watchdog timer Example -# # CONFIG_EXAMPLES_WATCHDOG is not set - -# -# wget Example -# - -# -# WLAN Example -# # CONFIG_EXAMPLES_WLAN is not set -# -# XML RPC Example -# - # # Interpreters # @@ -700,74 +495,19 @@ CONFIG_EXAMPLES_ELF_DEVPATH="/dev/ram0" # # Networking Utilities # - -# -# DHCP client -# # CONFIG_NETUTILS_DHCPC is not set - -# -# DHCP server -# # CONFIG_NETUTILS_DHCPD is not set - -# -# FTP client -# # CONFIG_NETUTILS_FTPC is not set - -# -# FTP server -# # CONFIG_NETUTILS_FTPD is not set - -# -# Name resolution -# +# CONFIG_NETUTILS_JSON is not set # CONFIG_NETUTILS_RESOLV is not set - -# -# SMTP -# # CONFIG_NETUTILS_SMTP is not set - -# -# TFTP client -# # CONFIG_NETUTILS_TELNETD is not set - -# -# TFTP client -# # CONFIG_NETUTILS_TFTPC is not set - -# -# THTTPD web server -# # CONFIG_NETUTILS_THTTPD is not set - -# -# uIP support library -# # CONFIG_NETUTILS_UIPLIB is not set - -# -# uIP web client -# # CONFIG_NETUTILS_WEBCLIENT is not set -# -# uIP web server -# - -# -# UDP Discovery Utility -# - -# -# XML-RPC library -# - # # ModBus # diff --git a/nuttx/include/nuttx/binfmt/elf.h b/nuttx/include/nuttx/binfmt/elf.h index aa04adaf2d..4770d82a3f 100644 --- a/nuttx/include/nuttx/binfmt/elf.h +++ b/nuttx/include/nuttx/binfmt/elf.h @@ -59,6 +59,9 @@ /**************************************************************************** * 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. @@ -71,7 +74,7 @@ struct elf_loadinfo_s off_t filelen; /* Length of the entire ELF file */ int filfd; /* Descriptor for the file being loaded */ #ifdef CONFIG_ELF_CONSTRUCTORS - uintptr_t ctors; /* Location of static constructors in memory */ + elf_ctor_t ctors; /* Pointer to a list of constructors */ uint16_t nctors; /* Number of constructors */ #endif uint16_t symtabidx; /* Symbol table section index */