Page 1 of 1

Static library can't allocate memory

Posted: Mon Jan 27, 2020 9:17 am
by stephenG
I exported a block of Matlab code into C to run on my NANO54415. I tested the code as a stand alone application and it functioned correctly without errors. The exported code was bigger than my application so I decided to make a static library out of it. When my larger application called the new library the Netburner faulted and rebooted. I trimmed down my code until I realized that accessing variables caused the seg fault. I created the following code that reproduces the error 100% of the time on my system. In older systems I would have checked linker commands to verify there was memory allocated to the library, but those quaint old flags appear to have gone away.

The static library:

libTest.h:

Code: Select all

#ifndef _LIB_TEST_H_
#define _LIB_TEST_H_

extern "C" void libTest(void);

#endif /* _LIB_TEST_H_ */
libTest.cpp:

Code: Select all

#include <stdio.h>
#include "libTest.h"

uint32_t state[10];

void libTest(void)
{

	iprintf("library test entry\n");
	state[0] = 5489;
	iprintf("library test exit\n");

}

The calling application:

Code: Select all

#include <predef.h>
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <smarttrap.h>
#include <taskmon.h>
#include <NetworkDebug.h>

#include <string.h>
#include <serial.h>
#include <command.h>

#include "libTest.h"

extern "C" {
void UserMain(void * pd);
}

#define SERIALPORT_TO_USE (0) //0 for the main port, 1 for the 10pin aux serial port
#define BAUDRATE_TO_USE (115200)
#define STOP_BITS (1)
#define DATA_BITS (8)


const char * AppName="StatLibDriver";


void * ProcessConnect( FILE *fp )
{
   const char *prompt;

   fiprintf( fp, "\nFront end Command Program\n");

   if ( ( int ) ( fp->_file ) == ( SERIAL_SOCKET_OFFSET ) )
   {
      prompt = "Serial0";
   }
   else if ( ( int ) ( fp->_file ) == ( SERIAL_SOCKET_OFFSET + 1 ) )
   {
      prompt = "Serial1";
   }
   else
   {
      prompt = "Telnet";
   }
   /* To test arbitray data tracking return the session number */
   return ( void * ) prompt;
}

void ProcessPrompt( FILE *fp, void *pData )
{
   /* For fun give each session  its nmumber in the prompt */
   fiprintf( fp, "\nTest:%s>", (char *)pData );
}

/* The command processing Callback */
int ProcessCommand( const char *command, FILE *fp, void *pData )
{
   iprintf("Calling libTest\n");

   libTest();

   return CMD_OK;
}

/* The User Authentication Callback */
int ProcessAuth( const char *name, const char *pass )
{
   /* For testing reject the set if they are the same */
   if ( strcmp( name, pass ) == 0 )
   {
      return CMD_FAIL;
   }
   else
   {
      return CMD_OK;
   }
}



void UserMain(void * pd) {
    InitializeStack();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();
    StartHTTP();
    EnableTaskMonitor();

    #ifndef _DEBUG
    EnableSmartTraps();
    #endif

    #ifdef _DEBUG
    InitializeNetworkGDB_and_Wait();
    #endif


 	// Setup console and ftp access
 	// Close the serial port in case it is already open.
 	SerialClose( SERIALPORT_TO_USE );

 	//Open the serial port
 	int fdserial = OpenSerial( SERIALPORT_TO_USE,
 									 BAUDRATE_TO_USE,
 									 STOP_BITS,
 									 DATA_BITS,
 									 eParityNone );

 	ReplaceStdio( 0, fdserial );
 	ReplaceStdio( 1, fdserial );
 	ReplaceStdio( 2, fdserial );

	CmdAuthenticateFunc = ProcessAuth; /* No authentication to start */
 	CmdCmd_func = ProcessCommand;
 	CmdConnect_func = ProcessConnect;
 	CmdPrompt_func = ProcessPrompt;

 	CmdIdleTimeout = TICKS_PER_SECOND * 60;

 	if(CmdStartCommandProcessor( MAIN_PRIO - 4) != CMD_OK)
 		iprintf("CmdStartCommandProcessor failed\n");

	CmdAddCommandFd( fdserial, FALSE, FALSE );

    iprintf("Lib test application started\n");
    while (1) {
        OSTimeDly(TICKS_PER_SECOND);
    }
}

Re: Static library can't allocate memory

Posted: Sat Feb 01, 2020 6:01 am
by jandarm
Hi, stephenG.

I've run your code just out of curiosity and got "Illegal instruction" signal.
NNDK 2.8.8, MOD5441X.

This is a mistake in library system makefiles: for NetBurner Library project template they are forgot to add C/C++ compiler platform-specific flags.
Thank you, NetBurner guys! =))))

SOLUTION: Add "-mcpu=54415 -DNANO54415 -DMCF5441X " to your C/C++ compiler flags in the project settings and rebuild libtest library. It will be work:

Code: Select all

13:00:46:502 Waiting 1sec to start 'A' to abort
13:00:47:558 Configured IP = 192.168.127.173
13:00:47:561 Configured Mask = 255.255.255.0
13:00:47:564 MAC Address=<...>
13:00:47:567 Front end Command Program
13:00:47:569 Lib test application started
13:00:52:546 Calling libTest
13:00:52:547 library test entry
13:00:52:549 library test exit
13:00:52:549
13:00:52:552 Test:Serial0>oCalling libTest
13:00:52:554 library test entry
13:00:52:555 library test exit
13:00:52:556
How did I recognize this mistake?
Because I know that MOD54415 doesn't have a FPU.

Disassembing listings:
original:

Code: Select all

(gdb) disass /m libTest
Dump of assembler code for function libTest():
14      {
   0x4002a360 <+0>:     linkw %fp,#-4

15
16          iprintf("library test entry\n");
=> 0x4002a364 <+4>:     movel #1073923660,%fp@(-4)				; <==== WTF?!
   0x4002a36c <+12>:    movew %fp@(-2),%sp@-					; <==== WTF?!
   0x4002a370 <+16>:    movew %fp@(-4),%sp@-					; <==== WTF?!
   0x4002a374 <+20>:    jsr 0x4002a18c <iprintf(char const*, ...)>
   0x4002a37a <+26>:    addql #4,%sp

17          state[0] = 5489;
   0x4002a37c <+28>:    movel #5489,0x40225248 <state>

18          iprintf("library test exit\n");
   0x4002a386 <+38>:    movel #1073923680,%fp@(-4)
   0x4002a38e <+46>:    movew %fp@(-2),%sp@-
   0x4002a392 <+50>:    movew %fp@(-4),%sp@-
   0x4002a396 <+54>:    jsr 0x4002a18c <iprintf(char const*, ...)>
   0x4002a39c <+60>:    addql #4,%sp

19
20      }
   0x4002a39e <+62>:    nop
   0x4002a3a0 <+64>:    unlk %fp
   0x4002a3a2 <+66>:    rts

End of assembler dump.
(gdb) 
Compiled with "-mcpu=54415 -DMOD5441X -DMCF5441X ":

Code: Select all

void libTest(void)
{
4002a360:   4e56 0000       linkw %fp,#0

    iprintf("library test entry\n");
4002a364:   4879 4002 c63c  pea 4002c63c <__DTOR_END__+0x1c24>	  ; <====  Now it looks good!
4002a36a:   4eb9 4002 a18c  jsr 4002a18c <iprintf>
4002a370:   588f            addql #4,%sp
    state[0] = 5489;
4002a372:   203c 0000 1571  movel #5489,%d0
4002a378:   23c0 4022 5248  movel %d0,40225248 <state>
    iprintf("library test exit\n");
4002a37e:   4879 4002 c650  pea 4002c650 <__DTOR_END__+0x1c38>
4002a384:   4eb9 4002 a18c  jsr 4002a18c <iprintf>
4002a38a:   588f            addql #4,%sp

}
4002a38c:   4e71            nop
4002a38e:   4e5e            unlk %fp
4002a390:   4e75            rts
    ...

Re: Static library can't allocate memory

Posted: Sat Feb 01, 2020 8:47 am
by TomNB
Hello,

Glad you have it working. Where did you make the modification for the flag? I don't have a version as old as 2.8.8, but in 2.9.2 I see in ldflags.mak:

ifndef CPUFLAG
CPUFLAG = mcpu=54415
endif

NBINCLUDE="$(NBROOT)/include" -I"$(NBROOT)/NANO54415/include"
LDFLAGS = -$(CPUFLAG) -Wl,-n -T$(PLATFORMROOT)/lib/NANO54415.ld -Wl,-R$(NBROOT)/NANO54415/lib/sys.ld
.....


There is also a difference in gcc releases:
2.9.2 upgraded to 8.1
2.9.0 upgraded to 5.2
2.8.x and earlier uses 4.2

Re: Static library can't allocate memory

Posted: Sat Feb 01, 2020 10:17 am
by jandarm
TomNB,

In NBEclipse go to Project Explorer window -> right click -> Properties -> C/C++ Build -> Settings -> Tool Settings tab -> GNU C++ Compiler -> Miscellaneous -> field Other flags

Re: Static library can't allocate memory

Posted: Wed Feb 05, 2020 7:52 am
by stephenG
jandarm,

Thank you! You're a life saver.

My coworkers weren't having this problem because their library projects were created in version 2.6.7 and exported into 2.9.1 so the flags were set correctly. I made the change and it's working correctly.

StephenG