C++ constructors work with ELF load now

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5273 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-10-29 19:32:05 +00:00
parent 71fad980c5
commit 5681b615ec
28 changed files with 1282 additions and 394 deletions
+75 -5
View File
@@ -41,6 +41,7 @@
#include <nuttx/compiler.h> #include <nuttx/compiler.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@@ -129,6 +130,9 @@
* Private Data * 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[] = static const char delimiter[] =
"****************************************************************************"; "****************************************************************************";
@@ -145,6 +149,53 @@ extern const int nexports;
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* 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 * Name: testheader
****************************************************************************/ ****************************************************************************/
@@ -168,6 +219,10 @@ int elf_main(int argc, char *argv[])
int ret; int ret;
int i; int i;
/* Initialize the memory monitor */
mm_initmonitor();
/* Initialize the ELF binary loader */ /* Initialize the ELF binary loader */
message("Initializing the ELF binary loader\n"); message("Initializing the ELF binary loader\n");
@@ -178,6 +233,8 @@ int elf_main(int argc, char *argv[])
exit(1); exit(1);
} }
mm_update(&g_mmstep, "after elf_initialize");
/* Create a ROM disk for the ROMFS filesystem */ /* Create a ROM disk for the ROMFS filesystem */
message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR); 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); exit(1);
} }
mm_update(&g_mmstep, "after romdisk_register");
/* Mount the file system */ /* Mount the file system */
message("Mounting ROMFS filesystem at target=%s with source=%s\n", message("Mounting ROMFS filesystem at target=%s with source=%s\n",
@@ -203,7 +262,9 @@ int elf_main(int argc, char *argv[])
elf_uninitialize(); 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++) for (i = 0; dirlist[i]; i++)
{ {
@@ -223,17 +284,26 @@ int elf_main(int argc, char *argv[])
exit(1); exit(1);
} }
mm_update(&g_mmstep, "after load_module");
ret = exec_module(&bin, 50); ret = exec_module(&bin, 50);
mm_update(&g_mmstep, "after exec_module");
if (ret < 0) if (ret < 0)
{ {
err("ERROR: Failed to execute program '%s'\n", dirlist[i]); 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"); unload_module(&bin);
sleep(4); mm_update(&g_mmstep, "after unload_module");
} }
message("End-of-Test.. Exiting\n"); mm_update(&g_mmstep, "End-of-Test");
return 0; return 0;
} }
+124
View File
@@ -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)
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
+1
View File
@@ -184,6 +184,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
break; break;
case R_ARM_ABS32: 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", 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); (long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value);
+1
View File
@@ -178,6 +178,7 @@ int arch_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
break; break;
case R_ARM_ABS32: 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", 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); (long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value);
+7
View File
@@ -34,6 +34,13 @@ endif
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 config SYMTAB_ORDEREDBYNAME
bool "Symbol Tables Ordered by Name" bool "Symbol Tables Ordered by Name"
default n default n
+7 -3
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* binfmt/binfmt_dumpmodule.c * 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> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * 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(" filename: %s\n", bin->filename);
bdbg(" argv: %p\n", bin->argv); bdbg(" argv: %p\n", bin->argv);
bdbg(" entrypt: %p\n", bin->entrypt); bdbg(" entrypt: %p\n", bin->entrypt);
bdbg(" ispace: %p size=%d\n", bin->ispace, bin->isize); bdbg(" mapped: %p size=%d\n", bin->mapped, bin->mapsize);
bdbg(" dspace: %p\n", bin->dspace); 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); bdbg(" stacksize: %d\n", bin->stacksize);
} }
return OK; return OK;
+52 -8
View File
@@ -70,6 +70,39 @@
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* 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 * 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; FAR _TCB *tcb;
#ifndef CONFIG_CUSTOM_STACK #ifndef CONFIG_CUSTOM_STACK
@@ -100,14 +133,14 @@ int exec_module(FAR const struct binary_s *bin, int priority)
/* Sanity checking */ /* Sanity checking */
#ifdef CONFIG_DEBUG #ifdef CONFIG_DEBUG
if (!bin || !bin->ispace || !bin->entrypt || bin->stacksize <= 0) if (!binp || !binp->entrypt || binp->stacksize <= 0)
{ {
err = EINVAL; err = EINVAL;
goto errout; goto errout;
} }
#endif #endif
bdbg("Executing %s\n", bin->filename); bdbg("Executing %s\n", binp->filename);
/* Allocate a TCB for the new task. */ /* 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 */ /* Allocate the stack for the new task */
#ifndef CONFIG_CUSTOM_STACK #ifndef CONFIG_CUSTOM_STACK
stack = (FAR uint32_t*)malloc(bin->stacksize); stack = (FAR uint32_t*)malloc(binp->stacksize);
if (!tcb) if (!tcb)
{ {
err = ENOMEM; err = ENOMEM;
@@ -130,11 +163,13 @@ int exec_module(FAR const struct binary_s *bin, int priority)
/* Initialize the task */ /* 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 #else
/* Initialize the task */ /* 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 #endif
if (ret < 0) if (ret < 0)
{ {
@@ -143,10 +178,12 @@ int exec_module(FAR const struct binary_s *bin, int priority)
goto errout_with_stack; 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 #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 */ /* 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; 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 */ /* Then activate the task at the provided priority */
ret = task_activate(tcb); 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); bdbg("task_activate() failed: %d\n", err);
goto errout_with_stack; goto errout_with_stack;
} }
return (int)pid; return (int)pid;
errout_with_stack: errout_with_stack:
+66 -10
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* binfmt/binfmt_loadmodule.c * 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> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -67,6 +67,39 @@
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* 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 * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -76,7 +109,12 @@
* *
* Description: * Description:
* Unload a (non-executing) module from memory. If the module has * 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: * Returned Value:
* This is a NuttX internal function so it follows the convention that * 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); bvdbg("Unmapping address space: %p\n", binp->mapped);
munmap(bin->ispace, bin->isize);
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); if (binp->alloc[i])
free(bin->dspace); {
bvdbg("Freeing alloc[%d]: %p\n", i, binp->alloc[i]);
free(binp->alloc[i]);
}
} }
} }
return OK; return OK;
} }
+23 -5
View File
@@ -114,7 +114,7 @@ static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo)
bdbg(" alloc: %08lx\n", (long)loadinfo->alloc); bdbg(" alloc: %08lx\n", (long)loadinfo->alloc);
bdbg(" allocsize: %ld\n", (long)loadinfo->allocsize); bdbg(" allocsize: %ld\n", (long)loadinfo->allocsize);
bdbg(" filelen: %ld\n", (long)loadinfo->filelen); bdbg(" filelen: %ld\n", (long)loadinfo->filelen);
#ifdef CONFIG_ELF_CONSTRUCTORS #ifdef CONFIG_BINFMT_CONSTRUCTORS
bdbg(" ctors: %08lx\n", (long)loadinfo->ctors); bdbg(" ctors: %08lx\n", (long)loadinfo->ctors);
bdbg(" nctors: %d\n", loadinfo->nctors); bdbg(" nctors: %d\n", loadinfo->nctors);
#endif #endif
@@ -211,13 +211,31 @@ static int elf_loadbinary(struct binary_s *binp)
/* Return the load information */ /* Return the load information */
binp->entrypt = (main_t)(loadinfo.alloc + loadinfo.ehdr.e_entry); binp->entrypt = (main_t)(loadinfo.alloc + loadinfo.ehdr.e_entry);
binp->ispace = (void*)loadinfo.alloc; binp->alloc[0] = (FAR void *)loadinfo.alloc;
binp->dspace = NULL;
binp->isize = loadinfo.allocsize;
binp->stacksize = CONFIG_ELF_STACKSIZE; 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, 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); elf_uninit(&loadinfo);
return OK; return OK;
-7
View File
@@ -32,13 +32,6 @@ config ELF_BUFFERINCR
will need to be read (such as symbol names). This value specifies the size 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 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 config ELF_DUMPBUFFER
bool "Dump ELF buffers" bool "Dump ELF buffers"
default n default n
+4 -4
View File
@@ -41,11 +41,11 @@ BINFMT_CSRCS += elf.c
# ELF library # ELF library
BINFMT_CSRCS += libelf_init.c libelf_uninit.c libelf_load.c \ BINFMT_CSRCS += libelf_bind.c libelf_init.c libelf_iobuffer.c libelf_load.c \
libelf_unload.c libelf_verify.c libelf_read.c \ libelf_read.c libelf_sections.c libelf_symbols.c libelf_uninit.c \
libelf_bind.c libelf_symbols.c libelf_iobuffer.c libelf_unload.c libelf_verify.c
ifeq ($(CONFIG_ELF_CONSTRUCTORS),y) ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y)
BINFMT_CSRCS += libelf_ctors.c BINFMT_CSRCS += libelf_ctors.c
endif endif
+34 -20
View File
@@ -85,6 +85,39 @@ int elf_verifyheader(FAR const Elf32_Ehdr *header);
int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer, int elf_read(FAR struct elf_loadinfo_s *loadinfo, FAR uint8_t *buffer,
size_t readsize, off_t offset); 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 * Name: elf_findsymtab
* *
@@ -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); int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo);
#endif #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 */ #endif /* __BINFMT_LIBELF_LIBELF_H */
+68 -220
View File
@@ -49,7 +49,7 @@
#include "libelf.h" #include "libelf.h"
#ifdef CONFIG_ELF_CONSTRUCTORS #ifdef CONFIG_BINFMT_CONSTRUCTORS
/**************************************************************************** /****************************************************************************
* Pre-Processor Definitions * Pre-Processor Definitions
@@ -67,166 +67,6 @@
* Private Functions * 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;
}
/****************************************************************************
* 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 * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -267,16 +107,21 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
return -ENOMEM; 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) if (ctoridx < 0)
{ {
/* This may not be a failure. -ENOENT indicates that the file has no /* This may not be a failure. -ENOENT indicates that the file has no
* static constructor section. * static constructor section.
*/ */
bvdbg("elf_findctors failed: %d\n", ctoridx); bvdbg("elf_findsection .ctors section failed: %d\n", ctoridx);
return ret == -ENOENT ? OK : ret; return ret == -ENOENT ? OK : ret;
} }
@@ -286,7 +131,9 @@ int elf_loadctors(FAR struct elf_loadinfo_s *loadinfo)
shdr = &loadinfo->shdr[ctoridx]; 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; ctorsize = shdr->sh_size;
loadinfo->nctors = ctorsize / sizeof(elf_ctor_t); 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 */ /* Check an assumption that we made above */
DEBUGASSERT(shdr->sh_entsize == sizeof(elf_ctor_t)); DEBUGASSERT(shdr->sh_size == loadinfo->nctors * sizeof(elf_ctor_t));
loadinfo->ctors = (elf_ctor_t)kmalloc(ctorsize); /* In the old ABI, the .ctors section is not allocated. In that case,
if (!loadinfo->ctors) * 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.
*/
if ((shdr->sh_flags & SHF_ALLOC) == 0)
{ {
bdbg("Failed to allocate memory for .ctors\n"); /* Not loaded -> Old ABI. */
return -ENOMEM;
loadinfo->newabi = false;
/* Allocate memory to hold a copy of the .ctor section */
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);
return ret;
}
/* Fix up all of the .ctor addresses. Since the addresses
* do not lie in allocated memory, there will be no relocation
* section for them.
*/
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;
}
} }
else
/* 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); /* Loaded -> New ABI. */
}
/* Fix up all of the .ctor addresses */ loadinfo->newabi = true;
for (i = 0; i < loadinfo->nctors; i++) /* Save the address of the .ctors (actually, .init_array) where it was
{ * loaded into memory. Since the .ctors lie in allocated memory, they
FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->ctors)[i]); * will be relocated via the normal mechanism.
*/
bvdbg("ctor %d: %08lx + %08lx = %08lx\n", i, loadinfo->ctors = (elf_ctor_t*)shdr->sh_addr;
*ptr, loadinfo->alloc, *ptr + loadinfo->alloc);
*ptr += loadinfo->alloc;
} }
} }
return OK; return OK;
} }
/**************************************************************************** #endif /* CONFIG_BINFMT_CONSTRUCTORS */
* 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.
*
****************************************************************************/
int elf_doctors(FAR struct elf_loadinfo_s *loadinfo)
{
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 */
+1 -57
View File
@@ -75,62 +75,6 @@
* Private Functions * Private 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.
*
****************************************************************************/
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 * Name: elf_allocsize
* *
@@ -292,7 +236,7 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
/* Find static constructors. */ /* Find static constructors. */
#ifdef CONFIG_ELF_CONSTRUCTORS #ifdef CONFIG_BINFMT_CONSTRUCTORS
ret = elf_loadctors(loadinfo); ret = elf_loadctors(loadinfo);
if (ret < 0) if (ret < 0)
{ {
+284
View File
@@ -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;
}
-9
View File
@@ -115,15 +115,6 @@ int elf_freebuffers(struct elf_loadinfo_s *loadinfo)
loadinfo->shdr = NULL; 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) if (loadinfo->iobuffer)
{ {
kfree((FAR void *)loadinfo->iobuffer); kfree((FAR void *)loadinfo->iobuffer);
+20
View File
@@ -91,6 +91,26 @@ int elf_unload(struct elf_loadinfo_s *loadinfo)
loadinfo->allocsize = 0; 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; return OK;
} }
-18
View File
@@ -62,24 +62,6 @@
* Private Constant Data * 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 * Private Functions
****************************************************************************/ ****************************************************************************/
+7 -5
View File
@@ -181,16 +181,18 @@ static int nxflat_loadbinary(struct binary_s *binp)
goto errout_with_load; 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->entrypt = (main_t)(loadinfo.ispace + loadinfo.entryoffs);
binp->ispace = (void*)loadinfo.ispace; binp->mapped = (void*)loadinfo.ispace;
binp->dspace = (void*)loadinfo.dspace; binp->alloc[0] = (void*)loadinfo.dspace;
binp->isize = loadinfo.isize; binp->mapsize = loadinfo.isize;
binp->stacksize = loadinfo.stacksize; binp->stacksize = loadinfo.stacksize;
nxflat_dumpbuffer("Entry code", (FAR const uint8_t*)binp->entrypt, 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); nxflat_uninit(&loadinfo);
return OK; return OK;
+2 -2
View File
@@ -160,8 +160,8 @@ LDNXFLATFLAGS = -e main -s 2048
# ELF module definitions # ELF module definitions
CELFFLAGS = $(CFLAGS) -mlong-calls CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs
CXXELFFLAGS = $(CXXFLAGS) -mlong-calls CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs
LDELFFLAGS = -r -e main LDELFFLAGS = -r -e main
ifeq ($(WINTOOL),y) ifeq ($(WINTOOL),y)
+1 -1
View File
@@ -388,7 +388,7 @@ CONFIG_ELF_ALIGN_LOG2=2
CONFIG_ELF_STACKSIZE=2048 CONFIG_ELF_STACKSIZE=2048
CONFIG_ELF_BUFFERSIZE=128 CONFIG_ELF_BUFFERSIZE=128
CONFIG_ELF_BUFFERINCR=32 CONFIG_ELF_BUFFERINCR=32
CONFIG_ELF_CONSTRUCTORS=y CONFIG_BINFMT_CONSTRUCTORS=y
CONFIG_SYMTAB_ORDEREDBYNAME=y CONFIG_SYMTAB_ORDEREDBYNAME=y
# #
@@ -51,8 +51,8 @@ SECTIONS
*/ */
*(.gnu.linkonce.t.*) *(.gnu.linkonce.t.*)
*(.init) *(.init) /* Old ABI */
*(.fini) *(.fini) /* Old ABI */
_etext = . ; _etext = . ;
} }
@@ -86,15 +86,17 @@ SECTIONS
.ctors : .ctors :
{ {
_sctros = . ; _sctors = . ;
*(.ctors) *(.ctors) /* Old ABI: Unallocated */
*(.init_array) /* New ABI: Allocated */
_edtors = . ; _edtors = . ;
} }
.ctors : .dtors :
{ {
_sdtors = . ; _sdtors = . ;
*(.dtors) *(.dtors) /* Old ABI: Unallocated */
*(.fini_array) /* New ABI: Allocated */
_edtors = . ; _edtors = . ;
} }
+21 -4
View File
@@ -49,9 +49,15 @@
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
#define BINFMT_NALLOC 2
/**************************************************************************** /****************************************************************************
* Public Types * 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 */ /* This describes the file to be loaded */
@@ -70,9 +76,15 @@ struct binary_s
*/ */
main_t entrypt; /* Entry point into a program module */ main_t entrypt; /* Entry point into a program module */
FAR void *ispace; /* Memory-mapped, I-space (.text) address */ FAR void *mapped; /* Memory-mapped, address space */
FAR struct dspace_s *dspace; /* Address of the allocated .data/.bss space */ FAR void *alloc[BINFMT_NALLOC]; /* Allocated address spaces */
size_t isize; /* Size of the I-space region (needed for munmap) */ #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) */ size_t stacksize; /* Size of the stack in bytes (unallocated) */
}; };
@@ -151,7 +163,12 @@ EXTERN int load_module(FAR struct binary_s *bin);
* *
* Description: * Description:
* Unload a (non-executing) module from memory. If the module has * 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: * Returned Value:
* This is a NuttX internal function so it follows the convention that * This is a NuttX internal function so it follows the convention that
+10 -9
View File
@@ -43,10 +43,13 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <elf32.h> #include <elf32.h>
#include <nuttx/binfmt/binfmt.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
@@ -59,9 +62,6 @@
/**************************************************************************** /****************************************************************************
* Public Types * 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 /* This struct provides a desciption of the currently loaded instantiation
* of an ELF binary. * of an ELF binary.
@@ -72,17 +72,18 @@ struct elf_loadinfo_s
uintptr_t alloc; /* Allocated memory with the ELF file is loaded */ uintptr_t alloc; /* Allocated memory with the ELF file is loaded */
size_t allocsize; /* Size of the memory allocation */ size_t allocsize; /* Size of the memory allocation */
off_t filelen; /* Length of the entire ELF file */ off_t filelen; /* Length of the entire ELF file */
int filfd; /* Descriptor for the file being loaded */ Elf32_Ehdr ehdr; /* Buffered ELF file header */
#ifdef CONFIG_ELF_CONSTRUCTORS FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */
elf_ctor_t ctors; /* Pointer to a list of constructors */ 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 */ uint16_t nctors; /* Number of constructors */
#endif #endif
uint16_t symtabidx; /* Symbol table section index */ uint16_t symtabidx; /* Symbol table section index */
uint16_t strtabidx; /* String table section index */ uint16_t strtabidx; /* String table section index */
uint16_t buflen; /* size of iobuffer[] */ uint16_t buflen; /* size of iobuffer[] */
Elf32_Ehdr ehdr; /* Buffered ELF file header */ int filfd; /* Descriptor for the file being loaded */
FAR Elf32_Shdr *shdr; /* Buffered ELF section headers */
uint8_t *iobuffer; /* File I/O buffer */
}; };
/**************************************************************************** /****************************************************************************