Add support uClibc++ excpetions. This involves additional handling for relative relation types, additional support for unwinding, as well as additional changes. The culmination of a big effort fromo Leo Aloe3132

This commit is contained in:
Gregory Nutt 2015-06-01 14:16:18 -06:00
parent 482d82c20e
commit 6068820bf3
9 changed files with 283 additions and 0 deletions

View File

@ -106,6 +106,13 @@ config ARMV7M_OABI_TOOLCHAIN
Most of the older buildroot toolchains are OABI and are named
arm-nuttx-elf- vs. arm-nuttx-eabi-
config ARMV7M_TARGET2_PREL
bool "R_ARM_TARGET2 is PC relative"
default n
depends on ELF
---help---
Perform a PC relative relocation for relocation type R_ARM_TARGET2
config ARMV7M_HAVE_STACKCHECK
bool
default n

View File

@ -48,6 +48,8 @@
#include <nuttx/arch.h>
#include <nuttx/binfmt/elf.h>
#ifdef CONFIG_ELF
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -60,6 +62,14 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef CONFIG_UCLIBCXX_EXCEPTION
extern void init_unwind_exidx(Elf32_Addr start, Elf32_Addr end);
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -204,6 +214,18 @@ int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
}
break;
#ifdef CONFIG_ARMV7M_TARGET2_PREL
case R_ARM_TARGET2: /* TARGET2 is a platform-specific relocation: gcc-arm-none-eabi
* performs a self relocation */
{
bvdbg("Performing TARGET2 link at addr=%08lx [%08lx] to sym=%p st_value=%08lx\n",
(long)addr, (long)(*(uint32_t*)addr), sym, (long)sym->st_value);
*(uint32_t*)addr += sym->st_value - addr;
}
break;
#endif
case R_ARM_THM_CALL:
case R_ARM_THM_JUMP24:
{
@ -464,3 +486,14 @@ int up_relocateadd(FAR const Elf32_Rela *rel, FAR const Elf32_Sym *sym,
bdbg("RELA relocation not supported\n");
return -ENOSYS;
}
#ifdef CONFIG_UCLIBCXX_EXCEPTION
int up_init_exidx(Elf32_Addr address, Elf32_Word size)
{
init_unwind_exidx(address, size);
return OK;
}
#endif
#endif /* CONFIG_ELF */

View File

@ -38,3 +38,13 @@ config ELF_DUMPBUFFER
depends on DEBUG && DEBUG_VERBOSE
---help---
Dump various ELF buffers for debug purposes
config ELF_EXIDX_SECTNAME
string "ELF Section Name for Exception Index"
default ".ARM.exidx"
depends on UCLIBCXX_EXCEPTION
---help---
Set the name string for the exception index section on the ELF modules to
be loaded by the ELF binary loader.
This is needed to support exception handling on loadable ELF modules.

View File

@ -245,6 +245,9 @@ static inline int elf_loadfile(FAR struct elf_loadinfo_s *loadinfo)
int elf_load(FAR struct elf_loadinfo_s *loadinfo)
{
size_t heapsize;
#ifdef CONFIG_UCLIBCXX_EXCEPTION
int exidx;
#endif
int ret;
bvdbg("loadinfo: %p\n", loadinfo);
@ -328,6 +331,18 @@ int elf_load(FAR struct elf_loadinfo_s *loadinfo)
}
#endif
#ifdef CONFIG_UCLIBCXX_EXCEPTION
exidx = elf_findsection(loadinfo, CONFIG_ELF_EXIDX_SECTNAME);
if (exidx < 0)
{
bvdbg("elf_findsection: Exception Index section not found: %d\n", exidx);
}
else
{
up_init_exidx(loadinfo->shdr[exidx].sh_addr, loadinfo->shdr[exidx].sh_size);
}
#endif
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the original address environment */

View File

@ -56,6 +56,16 @@ SECTIONS
_etext = . ;
}
.ARM.extab :
{
*(.ARM.extab*)
}
.ARM.exidx :
{
*(.ARM.exidx*)
}
.rodata :
{
_srodata = . ;

View File

@ -320,6 +320,25 @@ int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym,
int up_relocateadd(FAR const Elf32_Rela *rel,
FAR const Elf32_Sym *sym, uintptr_t addr);
#ifdef CONFIG_UCLIBCXX_EXCEPTION
/****************************************************************************
* Name: up_init_exidx
*
* Description:
* Load the boundaries of the Exception Index ELF section in order to
* support exception handling for loaded ELF modules.
*
* Input Parameters:
* address - The ELF section address for the Exception Index
* size - The size of the ELF section.
*
* Returned Value:
* Always returns Zero (OK).
*
****************************************************************************/
int up_init_exidx(Elf32_Addr address, Elf32_Word size);
#endif
/****************************************************************************
* Name: up_coherent_dcache
*

View File

@ -41,6 +41,9 @@ ASRCS =
CSRCS =
CXXSRCS = libxx_cxapurevirtual.cxx libxx_eabi_atexit.cxx libxx_cxa_atexit.cxx
ifeq ($(CONFIG_UCLIBCXX_EXCEPTION),y)
CXXSRCS += libxx__gnu_unwind_find_exidx.cxx
endif
# Some of the libxx/ files are not need if uClibc++ is installed because
# uClibx++ replaces them

View File

@ -0,0 +1,106 @@
//***************************************************************************
// libxx/libxx__gnu_unwind_find_exidx.cxx
//
// Copyright (C) 2015 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 "libxx__gnu_unwind_find_exidx.hxx"
//***************************************************************************
// Pre-processor Definitions
//***************************************************************************
//***************************************************************************
// Private Data
//***************************************************************************
//***************************************************************************
// Operators
//***************************************************************************
//***************************************************************************
// Name: __gnu_Unwind_Find_exidx
//
// Description:
// This function is called (if exists) by the gcc generated unwind
// run-time in order to retrieve an alternative .ARM.exidx Exception
// index section.
// This is the case for an ELF module loaded by the elf binary loader.
// It is needed to support exception handling for loadable ELF modules.
//
// NOTES:
//
// 1. The section to be searched is chosen by the address of the calling
// site: if we are in a runtime loaded ELF, the code will be executed
// in ram ( > 0x20000000 ) otherwise we will be executing code from
// flash (0x08000000) (running nuttx from ram will break this logic)
//
// 2. __exidx_start and __exidx_end refers to main nuttx elf image and
// are defined in its linker script.
//
// 2. __exidx_start_elf and __exidx_end_elf refers to the elf module
// loaded by the elf binary loader, and are initialized at run-time.
//
// 3. TODO: if nuttx itself is running from ram, this logic will not work
//
// 4. TODO: in order to support multiple elf modules running at the same
// time, this error logic needs to be extended to store multiple
// start/end ranges that refers to the loaded binaries.
//
//***************************************************************************
extern "C"
{
void init_unwind_exidx(Elf32_Addr start, Elf32_Word size)
{
__exidx_start_elf = (__EIT_entry *) start;
__exidx_end_elf = __exidx_start_elf + size;
}
_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr return_address, int *nrecp)
{
if (return_address < 0x20000000)
{
*nrecp = &__exidx_end - &__exidx_start;
return (_Unwind_Ptr) &__exidx_start;
}
else
{
*nrecp = (__exidx_end_elf - __exidx_start_elf) / sizeof(__EIT_entry);
return (_Unwind_Ptr) __exidx_start_elf;
}
}
}

View File

@ -0,0 +1,80 @@
//***************************************************************************
// lib/libxx__gnu_unwind_find_exidx.hxx
//
// Copyright (C) 2015 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.
//
//***************************************************************************
#ifndef __LIBXX_LIBXX__GNU_UNWIND_FIND_EXIDX_HXX
#define __LIBXX_LIBXX__GNU_UNWIND_FIND_EXIDX_HXX
extern "C"
{
//***************************************************************************
// Included Files
//***************************************************************************
#include <elf32.h>
#include <unwind.h>
//***************************************************************************
// Pre-processor Definitions
//***************************************************************************
//***************************************************************************
// Public Types
//***************************************************************************/
typedef struct __EIT_entry
{
_uw fnoffset;
_uw content;
} __EIT_entry;
//***************************************************************************
// Public Variables
//***************************************************************************
extern __EIT_entry __exidx_start;
extern __EIT_entry __exidx_end;
__EIT_entry *__exidx_start_elf;
__EIT_entry *__exidx_end_elf;
//***************************************************************************
// Public Function Prototypes
//***************************************************************************
_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr return_address, int *nrecp);
} // extern "C"
#endif // __LIBXX__GNU_UNWIND_FIND_EXIDX_HXX