Problems linking with C++ and EABI

Hi all

I’ve recently embarked on upgrading our application from the old ELF toolchain (which still used GCC4.0.1) over to the newer EABI toolchain. However, our project is written in C++, and when attempting to compile I’m getting trouble with the linker complaining that libg can’t find certain C methods like _kill, _pid and _fstat. I’ve managed to reproduce the problem by porting the C hello_world program to C++.

Here is the ported code:

/**********************************************************************************************************************/
/*  Hello_World.c   -  Copyright Sierra Wireless Inc. (c) 2010														  */
/*                                                                                                                    */
/*                                                                                                                    */
/* LICENSE                                                                                                            */
/* =======                                                                                                            */
/* If no specific agreement has been signed, this Source Code is subject to the following license terms:              */
/* http://www.sierrawireless.com/productsandservices/AirPrime/Sierra_Wireless_Software_Suite/License/Userlicense.aspx */
/* If you modify this file, you are subject to the contribution rules described into this license                     */
/**********************************************************************************************************************/


/***************************************************************************/
/*  File       : Hello_World.c                                             */
/*-------------------------------------------------------------------------*/
/*  Object     : Customer application                                      */
/*                                                                         */
/*  contents   : Customer main procedures                                  */
/*                                                                         */
/***************************************************************************/

/***************************************************************************/
/*  Include files                                                          */
/***************************************************************************/
extern "C"{
#include "wm_types.h"
#include "adl_str.h"
#include "adl_port.h"
#include "adl_traces.h"
#include "adl_AppliInit.h"
#include "adl_RspHandler.h"
#include "adl_TimerHandler.h"
}
#ifndef __GNU_GCC__
/*****************************************************************************/
/*  Macro   : DECLARE_CALL_STACK                                             */
/*---------------------------------------------------------------------------*/
/*  Object  : The GCC compiler and GNU Newlib (standard C library)           */
/*            implementation require more stack size than ARM compilers. If  */
/*            the GCC compiler is used, the Open AT® application has to be   */
/*            declared with greater stack sizes.                             */
/*                                                                           */
/*---------------------------------------------------------------------------*/
/*  Variable Name     |IN |OUT|GLB|  Utilization                             */
/*--------------------+---+---+---+------------------------------------------*/
/*  X                 | X |   |   |  required stack size                     */
/*--------------------+---+---+---+------------------------------------------*/
#define DECLARE_CALL_STACK(X)   (X)
#else /* #ifndef __GNU_GCC__ */
#define DECLARE_CALL_STACK(X)   (X*3)
#endif /* #ifndef __GNU_GCC__ */

extern "C"
{
// Application tasks prototypes
extern void main_task ( void );

}

// Application tasks declaration table
const adl_InitTasks_t adl_InitTasks [] =
{
    { main_task,  DECLARE_CALL_STACK ( 1024 ), "main", 1 },
    { 0, 0, 0, 0 }
};

/***************************************************************************/
/*  Function   : HelloWorld_TimerHandler                                   */
/*-------------------------------------------------------------------------*/
/*  Object     : Timer handler                                             */
/*                                                                         */
/*-------------------------------------------------------------------------*/
/*  Variable Name     |IN |OUT|GLB|  Utilisation                           */
/*--------------------+---+---+---+----------------------------------------*/
/*  ID                |   |   |   | Timer ID                               */
/*--------------------+---+---+---+----------------------------------------*/
/*  Context           |   |   |   | Context                                */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void HelloWorld_TimerHandler ( u8 ID, void * Context )
{
    /* Send a trace: Hello World */
    TRACE (( 1, "Embedded : Hello World" ));
    /* Send a response: Hello World */
    adl_atSendResponse ( ADL_AT_UNS, "\r\nHello World from Open-AT\r\n" );
}



/***************************************************************************/
/*  Function   : main_task                                                 */
/*-------------------------------------------------------------------------*/
/*  Object     : Customer application initialisation                       */
/*                                                                         */
/*-------------------------------------------------------------------------*/
/***************************************************************************/

void main_task ( void )
{
	adl_InitType_e adl_InitType = adl_InitGetType ();
    TRACE (( 1, "Embedded : Appli Init" ));

    /* Set 1s cyclic timer */
    adl_tmrSubscribe ( true, 10, ADL_TMR_TYPE_100MS, HelloWorld_TimerHandler );
}

And these are the linker errors I get:

09:35:05 **** Rebuild of configuration [Target]_ARM_EABI_GCC_Debug for project eabi2 ****
Info: Internal Builder is used for build
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.7.4\\bin\\arm-none-eabi-g++.exe" -D__OAT_API_VERSION__=637 -D__WIP_PLUGIN_VERSION__=543 -D__Security_PLUGIN_VERSION__=105 -D__DEBUG_APP__ -DDS_TARGET_BB0 -DDS_DEBUG -D__arm -D__GNU_GCC__ -D__irq= "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.Security.1.5.0.201108111447_1.5.0.201108111447\\resources/Security/itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.37.0.201202060950_6.37.0.201202060950\\resources/ADL/itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.37.0.201202060950_6.37.0.201202060950\\resources/ADL/basic" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.WIP.5.43.3.201212250709_5.43.3.201212250709\\resources/WIP/itf" "-IC:\\workspace\\eabi2\\inc" -O0 -Os -g -ggdb3 -Wall -c -fshort-enums -fdollars-in-identifiers -fno-strict-aliasing -fno-common -fomit-frame-pointer -mthumb-interwork -mthumb -march=armv5te -mapcs -mno-apcs-stack-check -o "src\\hello_world.o" "..\\src\\hello_world.cpp" 
..\src\hello_world.cpp: In function 'void HelloWorld_TimerHandler(u8, void*)':
..\src\hello_world.cpp:85:73: warning: deprecated conversion from string constant to 'ascii* {aka char*}' [-Wwrite-strings]
..\src\hello_world.cpp: In function 'void main_task()':
..\src\hello_world.cpp:100:17: warning: unused variable 'adl_InitType' [-Wunused-variable]
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.7.4\\bin\\arm-none-eabi-gcc.exe" -D__OAT_API_VERSION__=637 -D__WIP_PLUGIN_VERSION__=543 -D__Security_PLUGIN_VERSION__=105 -D__DEBUG_APP__ -DDS_TARGET_BB0 -DDS_DEBUG -D__arm -D__GNU_GCC__ -D__irq= "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.Security.1.5.0.201108111447_1.5.0.201108111447\\resources/Security/itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.37.0.201202060950_6.37.0.201202060950\\resources/ADL/itf" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.37.0.201202060950_6.37.0.201202060950\\resources/ADL/basic" "-IC:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.WIP.5.43.3.201212250709_5.43.3.201212250709\\resources/WIP/itf" "-IC:\\workspace\\eabi2\\inc" -O0 -Os -ggdb3 -Wall -c -fshort-enums -fdollars-in-identifiers -fno-strict-aliasing -fno-common -fomit-frame-pointer -mthumb-interwork -mthumb -march=armv5te -msoft-float -mapcs -mno-apcs-stack-check -o "src\\generated.o" "..\\src\\generated.c" 
"C:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\tools\\armeabigcc\\4.7.4\\bin\\arm-none-eabi-g++.exe" -Wl,--script,gcc.lkopt -Wl,-( "src\\hello_world.o" "src\\generated.o" -Os -O2 -fshort-enums -fdollars-in-identifiers -ggdb3 -u _siwiStubsImplementation -nostartfiles -fomit-frame-pointer -mthumb-interwork -mthumb -march=armv5te -msoft-float -mfpu=fpa -mapcs -mno-apcs-stack-check -Wl,-nmagic -Wl,-Map,eabi2.map -laeabi "-LC:\\Program Files (x86)\\Sierra Wireless\\Developer Studio\\configuration\\org.eclipse.osgi\\bundles\\60\\1\\.cp\\libs\\oat" "C:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.Security.1.5.0.201108111447_1.5.0.201108111447\\resources\\Security\\RVDS_Jamming.lib" "C:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.Security.1.5.0.201108111447_1.5.0.201108111447\\resources\\Security\\RVDS_wipssl.lib" "C:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.os.model.6.37.0.201202060950_6.37.0.201202060950\\resources\\ADL\\RVDS_ADL.lib" "C:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.WIP.5.43.3.201212250709_5.43.3.201212250709\\resources\\WIP\\RVDS_WIP.lib" "C:\\Program Files (x86)\\Sierra Wireless\\Embedded Software\\com.wavecom.openat.ide.spm.lib.plugin.model.WIP.5.43.3.201212250709_5.43.3.201212250709\\resources\\WIP\\RVDS_WIPSoftLib.lib" -Wl,-) -oeabi2.axf 
c:/program files (x86)/sierra wireless/developer studio/tools/armeabigcc/4.7.4/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/thumb\libg.a(lib_a-abort.o): In function `abort':
abort.c:(.text.abort+0xa): undefined reference to `_exit'
c:/program files (x86)/sierra wireless/developer studio/tools/armeabigcc/4.7.4/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/thumb\libg.a(lib_a-signalr.o): In function `_kill_r':
signalr.c:(.text._kill_r+0xe): undefined reference to `_kill'
c:/program files (x86)/sierra wireless/developer studio/tools/armeabigcc/4.7.4/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/thumb\libg.a(lib_a-signalr.o): In function `_getpid_r':
signalr.c:(.text._getpid_r+0x2): undefined reference to `_getpid'
collect2.exe: error: ld returned 1 exit status

09:35:05 Build Finished (took 689ms)

As you might be able to pick up from the compiler flags, this is for the SL6087 with a 6.47 OS

Any help you could give in getting this to compile on 6.47 would be great. If there’s any more information you need just ask.

It seems I found a solution, although I feel it isn’t ideal. I added stubs to the end of the file in an extern “C” block for the missing methods that the linker was complaining about, _exit, _getpid etc. I used the stub formats found in this thread: [url]https://forum.sierrawireless.com/t/using-oatlua4-under-ds/5972/1].

Hopefully these don’t cause any issues if a library tries to call them.

Just for reference in the future, the help documentation gives you this information.
You can find it under Help -> Help Contents -> Developer Studio User Guide -> Build System -> Advanced Topics -> Adding C++ Code

The Header “Tool Chain Specifics” deals with the extra code you need depending on the Target Mode.

If you are using ARM EABI GCC then it should link you to the file “/com.wavecom.openat.ide.ebs.ui.help/html/eabi_stub.c”