Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

linker question

Altera_Forum
Honored Contributor II
984 Views

hello, 

 

In my project, some global variables are placed in a library. These variables are used in a class that also has a global instance in that library. The constructor of that class places pointers to the data in a list that is defined elsewhere. 

The data is never looked at directly, but through that list. 

 

It seems that the linker is getting rid of all data used in this manner, so the data is not available.  

 

When I put all data and the instance of the class in the main cpp file, the linker puts it in the executable.  

 

Any attributes, linker options, ... available to force the system to keep the data in the executable, and to call the constructor of the "unused" instances?? 

 

Thanks, 

 

Stefaan
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
294 Views

Some progress. 

 

It seems that the file as a whole entity is removed. As soon as I force the linker to use a small part of the file, the rest of tha data is also available. 

 

I've put another global variable in the source file (int dummy;), and use it in the main source file (extern int dummy;).  

 

The problem is that I will have a lot of such issues, and I can not use a dummy variable in the main project file for every library I use. 

 

Any idea's? 

 

 

Stefaan
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

Hi , 

 

> Any idea's? 

 

Perhaps, but ... 

 

> In my project, some global variables are placed in a library. 

 

Ok. 

 

> These variables are used in a class that also has a global instance in that library. 

 

The variables are referenced by an object that is ... instantiated by the code in the 

library? Is the object statically constructed? Or is there a static method (factory 

method)? 

 

> The constructor of that class places pointers to the data in a list that is defined 

> elsewhere. 

 

Elsewhere in the lib, app? Is the list statically allocated? 

 

> The data is never looked at directly, but through that list. 

 

... it's not clear to me what you are doing. Could you provide a small concrete 

example, indicating what is in the library, and what is in the app, and how they 

interact? It may help me (and others) understand better. I think I'm close ... but 

my mind is not as good as it used to be ;-) 

 

Regards, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

I can explain for sure (I hope you want to read a lot of text, it's not easy to explain in a few words) : 

 

I use a kind of "filesystem" in RAM. Most of the data is read only, but files are also used for updating, writing to EEPROM, FLASH, ... 

 

The "FileSystem" class contains a list "File" instances. The "FileSystem class is completly static. So for example the html server can open a file like this : FileSystem::Open(char* filename). 

 

The specific functionality behind a file is done in a class derived from "File". This can be a simple "RamFile" that contain some data on a specific RAM address.  

 

For example : 

 

static const char data = "This is a test file containing just a simple text"; RamFile TestDataFile("testdata.txt", data, strlen(data)); 

 

The constructor of RamFile calls the constructor of File, wich links its 'this' pointer in the FileSystem. 

 

 

Now the compile and link process : 

 

My system is set up to use different pieces of code in seperate libraries. For example "ethlib.a" (tcp/ip stack) , "oslib.a" (operating system) and "boardlib.a" (board component interfaces like SPI, flash, ...). The same libraries are used in different projects. 

 

Besides the libraries, I have a set of source files (and corresponding objects) generated for a specific project. So the linker uses these objects directly, togheter with the archived objects in the libraries. 

 

Now the problem starts : I want to have some files with information about the board components in a webpage --> so this belongs to "boardlib.a".  

 

I construct a file called "html_board.cpp" and puts something in like the above example. I add to the makefile for the library and generate the library. 

 

After recompiling the whole project, I suspect the newly added file in the filesystem to be available, but no, even the data itself is not in executable (verified in an object dump). 

 

Next step to put the two lines as in the example in one of the projects source files, and not in the library --> system works like expected. 

 

Next idea : maybe the linker ignores "html_board.o" file (part of the library)because none of it is referenced elsewhere. To test this theary, I changed above "html_board.cpp" example to : 

 

int dummy = 0; static const char data = "This is a test file containing just a simple text"; RamFile TestDataFile("testdata.txt", data, strlen(data)); 

 

and in one of the projects source files : 

 

 

extern int dummy; void foo() { dummy++; ... ... } 

 

I make sure foo() is called and dummy can not be optimized away. Surprise : the "testdata.txt" is in the FileSystem.  

 

So I'm pretty sure now, the linker ignores the "html_board.o" from the boardlib.a completely. As soon that there is something in the file used, the whole file is used. 

 

I hope there is a simple solution to force the compiler to instantiate my file file objects. 

 

I tried with "static const" and the compiler option '-fkeep-static-consts", but no good result. 

 

 

Hope its clear now, sorry for the long story. 

 

Stefaan
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

Hi Stefaan, 

 

I think I understand now ... 

 

In your example, is the FileSystem object ever referenced by your application? 

If not, it won't get pulled in -- it's just another library that is not needed for 

unresolved references. 

 

If you structure your FileSystem class (object) as a Singleton you can make sure 

it gets reference and linked in. The Singleton pattern will also allow you to 

dynamically allocate the FileSystem object. Something like: 

 

<div class='quotetop'>QUOTE </div> 

--- Quote Start ---  

class FileSystem { 

public: 

    static FileSystem *Instance (); 

protected: 

    FileSystem (); 

private: 

    static FileSystem* _inst; 

}; 

 

/* Implementation */ 

FileSystem *FileSystem::_inst = NULL; 

FileSystem *FileSystem::Instance () 

    if (_inst ==NULL) 

        _inst = new FileSystem; 

    return _inst; 

}[/b] 

--- Quote End ---  

 

 

Then anywhere in your application code you can just grab a reference: 

 

FileSystem *fs = FileSystem::Instance(); 

fs->open (...);  

 

As long as you reference the Instance operation somewhere, it&#39;ll get pulled in. 

This also avoids any potential issues associated with static construction. 

 

From a linker point-of-view, it&#39;s really no different than dummy++, but from 

a style point-of-view, C++ programmers will see a familiar design pattern. 

 

Hope this helps ... and I hope I didn&#39;t completely miss the boat on this one ;-) 

 

Regards, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

The problem is not the filesystem itself. It works with other files that already are in the system (but not in a library for the moment) 

 

The problem is some instances of File (or a derived version of File). Because the Filesystem::Open() uses a character string (the filename) to look up what the File instance is to use.  

 

So if the tftp server is getting a request for the "testdata.txt", the FileSystem looks for the File instance attached to that name, and returns a pointer to TestDataFile (see examples in my previous post). Here the TestDataFile is never accessed elsewhere in the code directly, and this is exactly what I want to achieve : some parts of the software generate some files with information about the system, without interaction with the main part of the software. It should be stupid if I have to change other parts of the sw if I add a file somewhere. 

 

I can understand your point about the singleton, but I think it will not help me, because in the source file with the problems, I don&#39;t need the FileSystem at all. It is the web server (or tftp, ... server) that uses the static FileSystem (Filesystem is a class with all static members, and has no real instance). 

 

 

Stefaan
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

Hi Steffan, 

 

Ok, I think I understand now: Your application, and the library code 

that your application references does not actually reference the underlying file 

data symbols -- yes? 

 

When the linker searches archive files, it only seeks to resolve undefined symbol 

references. When the reference is found, the contents of the file (from the archive) 

where the symbol is defined is linked in. If it searches an archive and does not find 

any unresolved symbols, the contents are _not_ linked in. 

 

A way around this is to use the the --whole-archive option. This will force all of 

the object files in an archive to be linked in -- even when no undefined references 

are found. You can (should) turn this option off again with --no-whole-archive. 

 

I have rarely used this feature, and I have yet to try it with nios2-elf ... so my 

experience with this is out-of-date and foggy at best. You might want to dig into 

the man pages ... or perhaps someone else can offer some insight. 

 

Very sorry I haven&#39;t been much help :-/ 

 

Regards, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

Hi smcnutt, 

 

No sorry, I&#39;m glad to discuss with someone, ... 

 

I will try your --whole-archive option, but this will make the whole executables for the different projects much bigger, because other parts that are not always used will be linked in. 

 

I&#39;m thinking a bit further on the way of using the "dummy variable" system, but then in an automated way, but I don&#39;t have a clear view on this yet. 

 

Or I can# include the source file with the html content into a source file that is used for sure in that library. This is probably not the most clean method, but will work good I think. 

 

If anyway something comes into your mind, please let me know. 

 

Thanks.
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

Hi Steffan, 

 

> but this will make the whole executables for the different projects much bigger 

 

If your archive contains only what you need, it won&#39;t be any larger if you wrap just 

that archive with --whole-archive and --no-whole-archive ... the ld info page describes 

this. 

 

Good luck, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

smcnutt, 

 

The --whole-archive changes indeed something, I have over 100 errors now, most of them seems to be multiple definitions. 

 

I tried to include the file with the problems in an other file from the same library, and this works perfect. Execept that it is a bit strange to include a .cpp file in an other .cpp file, it works fine for me. At the moment, I can live with this solution. 

 

Time to get on with the rest of the project... 

 

 

Have a nice day, 

 

Stefaan.
0 Kudos
Altera_Forum
Honored Contributor II
294 Views

Hi Stefaan, 

 

> most of them seems to be multiple definitions. 

 

Understood. I tried this myself -- when I wrap the library with the "whole" and 

"no-whole" options I don&#39;t have any problems. E.g. for libfoobar.a : 

 

$ nios2-elf-gcc -o test -Wl,--whole-archive -lfoobar -Wl,--no-whole-archive main.c 

 

Regards, 

--Scott
0 Kudos
Reply