mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-06 19:31:35 +08:00
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 = . ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user